如何在C#中将列表与现有列表进行比较排序?

4
我有一个包含ID列表的 List<int> allIDs,它按照原始顺序排列。我正在创建一个元素选择器,允许用户将ID从这个列表添加到另一个 List<int> selectedIDs 中或者从中删除。现在,我已经完成了所有的工作,但是当用户删除并稍后再次添加相同的元素时,它只会被添加到列表的末尾 (selectedIDs.Add( id ))。
我想要将元素插入到它原来的位置,使用 allIDs 作为它原来位置的参考。
以下是一些列表摘录,以便更好地理解上述内容:
List<int> allIDs = new List<int> {10, 11, 9, 155, 12, 299, 15...};
List<int> selectedIDs = new List<int> { 10, 9, 155, 299, 15... }

现在假设我从selectedIDs列表中删除了id=299,稍后想再次添加它。我如何将其插入到15515之间?我知道可以使用list.Insert(obj, index)方法在列表中的任何位置进行插入,但最简单的编程方式是什么?


你是否反对使用SortedList类 - Joshua Drake
4
这些列表显然一开始就没有排序... - Jacek Gorgoń
@JacekGorgoń,兄弟,今天不是我读问题的好日子。 :( - Joshua Drake
6个回答

6
如果我正确理解您的要求:
var ordered = selectedIDs.OrderBy(sID => allIDs.IndexOf(sID));

这将按照每个ID在原始完整列表中的索引顺序对所选ID列表进行排序。

经过广泛的测试,这在10个案例中有9个是有效的。然而,一些项目仍然被添加到列表的顶部,没有应用任何排序。 - Kris Selbekk
1
@KrisSelbekk:如果您能重现它,那么您应该提出一个新问题,这可能对其他人也很有趣。您能展示一个例子吗?您确定原因不是LINQ的延迟执行吗?您可以通过在结尾处调用ToList()轻松解决。 - Tim Schmelter

1

伪代码如下:

在第一个列表中查找您的元素的索引。

如果此索引为0,则将您的元素添加到列表开头。

否则,索引=x;

取出索引为x-1的元素;

如果索引为x-1的元素在您的列表中,则在其后面添加新元素。

否则,如果x-2≥0,则再次循环并使用索引为x-2的元素。

最终,您将得到已包含在列表中的前一个元素的索引,并将在此索引+1处插入新元素。


1
如果您使用 SortedDictionary而不是List会怎么样呢?键将是索引,值将是ID。

1
一个选项是使用 List<MyClass> 而不是 List<int>。 MyClass 将具有两个属性,一个 intbool shouldDisplay。而不是从第一个列表中删除项目,您可以将它们标记为隐藏或不显示。要取消删除它们,只需将它们设置为“可见”即可。

1

Tim的答案非常简洁和酷,但复杂度相当高。以下代码应该更快,并且在更大的列表上更可用,尽管不够紧凑。

public class IdWithFlag
{
     public int Id { get; set; }
     public bool Selected { get; set; }
}

Dictionary<int, IdWithFlag> allIDs = ... // populate somehow, perhaps a custom cast operator would help

现在每次您添加/删除所选ID时,重新生成另一个列表如下:

allIDs[currentlyChangedId].Selected = ... // added or removed?

List<int> selectedIDs = allIDs.Values
    .Where(id => id.Selected)
    .Select(id => id.Id)
    .ToList();

更加复杂,但计算复杂度更好。


1

这不是最高效的答案,但我认为这是最容易编码的答案:

List<int> allIDs = new List<int> { 10, 11, 9, 155, 12, 299, 15 };
List<int> selectedIDs = new List<int> { 299, 10, 9, 15, 11 };

// this will ensure the sort order...
var newSel = (from a in allIDs
    join s in selectedIDs on a equals s
    select a).ToList();

selectedIDs = newSel;

生成的输出将始终按照allIDs中数字的顺序进行排序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接