如何按多个 T.attributes 对 List<T> 进行排序?

Posted

技术标签:

【中文标题】如何按多个 T.attributes 对 List<T> 进行排序?【英文标题】:How can I sort a List<T> by multiple T.attributes? 【发布时间】:2011-06-20 00:44:27 【问题描述】:

假设我有一个歌曲列表。

Song 
    public string Name = "";
    public int PlayOrder = 0;
    

现在我想首先按 PlayOrder 从零开始对它们进行排序,然后按名称按字母顺序排列。

因此,一组排序结果的示例将是 (Name, PlayOrder):

/*
    Pachelbel's Canon, 0
    A Happy Song, 4
    Beethoven's 5th, 4
    Some Other Song, 7
*/

看看 PlayOrder = 4 是如何按字母顺序排列的?这就是我想要的。

现在我只按一个字段排序:

List<Song> final = new List<Song>();

...

final.Sort((x, y) => x.PlayOrder.CompareTo(y.PlayOrder));

return final;

如上所示,我怎样才能按名称排序?

【问题讨论】:

【参考方案1】:
return final.OrderBy(s => s.PlayOrder).ThenBy(s => s.Name);

【讨论】:

请注意,这将返回一个新的IEnumerable&lt;Song&gt; 序列,而不是就地对原始列表进行排序。 如果我希望它返回一个列表,我可以在最后添加一个 .ToList() 吗? 在您声明 OrderBy 执行稳定排序的其他评论中,您描述了稳定排序的含义。你能用同样的例子解释一下不稳定的排序吗? 她是一个很好的解释***.com/questions/3615100/… Ooooooh 使用 THENBY - 但是当然!伙计,我需要更频繁地进行 RTFM :)【参考方案2】:

如果您想继续使用排序方法,您需要让比较功能更智能:

final.Sort((x, y) => 
    var ret = x.PlayOrder.CompareTo(y.PlayOrder);
    if (ret == 0) ret = x.Name.CompareTo(y.Name);
    return ret;
);

如果您想使用 LINQ,那么您可以使用 K Ivanov 发布的内容。

【讨论】:

注意:Sort()“执行不稳定排序”,而OrderBy“执行稳定排序;即如果两个元素的键相等,则保留元素的顺序” 这是如何工作的?花括号之间发生了什么,我如何才能返回一个var?它回归什么?花括号内的代码会运行一次还是多次? 花括号中的代码是 lambda 表达式的主体,与您在问题中使用的 lambda 表达式相同。问题是,要做到这一点,我需要超过 1 个语句,所以我必须在身体周围放置大括号。基本上那里的代码是比较代码,排序算法会多次调用它(按: nlogn 的顺序)。【参考方案3】:

如果您只有一种首选的歌曲排序方式class,您应该实现IComparable 和/或IComparable&lt;Song&gt;

List<Song> songs = GetSongs();
songs.Sort(); // Sorts the current list with the Comparable logic

如果您有多种存储列表的方式,IEqualityComparer&lt;T&gt; 是您想要实现的接口。然后您可以在List&lt;T&gt;Sort() 中提供该比较器作为参数。

【讨论】:

以上是关于如何按多个 T.attributes 对 List<T> 进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

对list中的多个map按某个属性的值排序,null值放到最后

jdk1.8中list按对象的多个属性去重,按对象的某个属性分组

集合List根据多个字段进行排序

在Kotlin中按多个字段对集合进行排序[重复]

如何对List集合中的对象进行按某个属性排序

如何对list<>数组内元素按从小到大排序?