根据预排序的列表对列表进行排序

7

我可以如何基于一个预先排序的列表对列表进行排序。

我的列表已经排序好了。比如,我的已排序列表是

{"Junior Developer", "Developer", "Senior Developer", "Project Lead"}

现在,我想按照与上面列表相同的顺序对任何子集进行排序。也就是说,如果我的输入是{"Developer", "Junior Developer"},我希望输出为{"Junior Developer", "Developer"}
如果输入为{"Project Lead", "Junior Developer", "Developer"},我希望输出为:
{"Junior Developer", "Developer", "Project Lead"}. 

我该如何实现相同的效果?

5
按照 .IndexOf() 进行排序。 - zerkms
1
只是为了扩展@zerkms的评论:input.OrderBy(x => bigSortedList.IndexOf(x)) - JleruOHeP
也许这不是最好格式化的问题,但它仍然是一个合法的问题。为什么会有负评? - cost
@cost 我也曾经想过同样的问题,但是赞数似乎已经自动处理了。至于格式方面,如果有人编辑它以符合标准并从中学习,我会非常高兴。谢谢! - Kanini
4个回答

11

最简单的方法是使用LINQ的.OrderBy扩展方法,以及您预先排序的集合的IndexOf方法(或等效方法)。这里的想法是使用不同的值作为“排序关键字”进行排序(这非常有用,因为通常我们希望根据对象的某个属性对其进行排序)。

var sorted = listToSort.OrderBy(s => listPreSorted.IndexOf(s)).ToList();

以下是一个使用数组的示例:http://ideone.com/7oshhZ


请注意,如果您的列表非常大,这种方法可能会很慢,因为需要按顺序查找目标列表中的每个项在已经排序好的集合中的位置(O(N * M),其中N是目标列表的长度,M是预先排序的列表的长度)。

为了克服这个限制,您可以生成一个查找映射,将您的预先排序列表的项目映射到它们的索引,然后在.OrderBy中使用此查找(这将具有O(N + M)的运行时间,并且如果需要,可以重用该查找):

var preSortedLookup =
        listPreSorted.Select((v, i) => new { Key = v, Value = i })
                     .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

var sorted = listToSort.OrderBy(s => preSortedLookup[s]).ToList();

2

如果两个列表中没有重复项,那么您可以简单地使用Intersect,它将保留顺序:

var allRoles = new[] {"Junior Developer", "Developer",
                      "Senior Developer", "Project Lead"};
var roles = new[] {"Developer", "Junior Developer"};
var sortedRoles = allRoles.Intersect(roles);

使用 IndexOf 进行排序可能比较高效,但除非列表很长,否则您不太可能注意到太大的差异。


1
@Mathew:不知道Intersect会保留顺序,谢谢! - Kanini

0

如果你面对大量数据,可以尝试使用字典结构?

1,

dictionary<string,int>

使用这个字典来存储字符串和索引

2、生成一个长度为你的字符串数量的虚拟数据list<string> result

3、然后定位正确的索引号,通过索引将字符串写入result


0
假设你有一个已排序的列表listA,另一个列表是listB。 每次从listB中读取元素时,检查该元素是否在listA中,并根据这个顺序排序你的列表。

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