LINQ 自定义排序
Posted
技术标签:
【中文标题】LINQ 自定义排序【英文标题】:LINQ Custom Sort 【发布时间】:2014-09-10 13:06:15 【问题描述】:我想要一个字母排序,但有一个例外。 我首先需要一个名称 =“Public”且 ID =“0”的组。 (宁愿使用 ID = 0) 之后,然后按名称对其余部分进行排序。 这不会首先公开。
public IEnumerable<GroupAuthority> GroupAuthoritysSorted
get
return GroupAuthoritys.OrderBy(x => x.Group.Name);
我想要的是:
return GroupAuthoritys.Where(x => x.ID == 0)
UNION
GroupAuthoritys.Where(x => x.ID > 0).OrderBy(x => x.Group.Name);
GroupAuthority 有一个公共属性 Group,Group 有公共属性 ID 和 Name。
我基本上使用了公认的答案
using System.ComponentModel;
namespace SortCustom
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
TestSort();
private void TestSort()
List<CustomSort> LCS = new List<CustomSort>();
LCS.Add(new CustomSort(5, "sss"));
LCS.Add(new CustomSort(6, "xxx"));
LCS.Add(new CustomSort(4, "xxx"));
LCS.Add(new CustomSort(3, "aaa"));
LCS.Add(new CustomSort(7, "bbb"));
LCS.Add(new CustomSort(0, "pub"));
LCS.Add(new CustomSort(2, "eee"));
LCS.Add(new CustomSort(3, "www"));
foreach (CustomSort cs in LCS) System.Diagnostics.Debug.WriteLine(cs.Name);
LCS.Sort();
foreach (CustomSort cs in LCS) System.Diagnostics.Debug.WriteLine(cs.Name);
public class CustomSort : Object, INotifyPropertyChanged, IComparable<CustomSort>
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
if (PropertyChanged != null) PropertyChanged(this, e);
private Int16 id;
private string name;
public Int16 ID get return id;
public String Name get return name;
public int CompareTo(CustomSort obj)
if (this.ID == 0) return -1;
if (obj == null) return 1;
if (obj is CustomSort)
CustomSort comp = (CustomSort)obj;
if (comp.ID == 0) return 1;
return string.Compare(this.Name, comp.Name, true);
else
return 1;
public override bool Equals(Object obj)
// Check for null values and compare run-time types.
if (obj == null) return false;
if (!(obj is CustomSort)) return false;
CustomSort comp = (CustomSort)obj;
return (comp.ID == this.ID);
public override int GetHashCode()
return (Int32)ID;
public CustomSort(Int16 ID, String Name)
id = ID;
name = Name;
【问题讨论】:
告诉我们class GroupAuthority
的定义。
@ClickRick GroupAuthority 有一个公共属性 Group 并且 Group 有公共属性 ID 和 Name。
请将其编辑到您的问题中。
GroupAuthoritys.OrderBy(x => x.Group.Name == "Public" && x.Group.ID == 0 ? 0 : 1, x.Group.Name);
在任何手机上,无法准确记住语法,但这是完成它的基本思路
【参考方案1】:
您需要使用比较函数,它们是从您的类型的两个实例返回一个整数的函数,如果两者相等则返回 0,如果第一个小于第二个则返回负值,如果第一个返回正值大于秒。
MSDN 有一个nice table,比文字更容易理解(*** 在 2014 年仍然不支持表格)
IComparer<T>
大多数排序方法都接受IComparer<T>
类型的自定义比较器实现,您应该创建一个封装Group
的自定义规则:
class GroupComparer : IComparer<Group>
public int Compare(Group a, Group b)
if (a != null && b != null && (a.Id == 0 || b.Id == 0))
if (a.Id == b.Id)
// Mandatory as some sort algorithms require Compare(a, b) and Compare(b, a) to be consitent
return 0;
return a.Id == 0 ? -1 : 1;
if (a == null || b == null)
if (ReferenceEquals(a, b))
return 0;
return a == null ? -1 : 1;
return Comparer<string>.Default.Compare(a.Name, b.Name);
用法:
items.OrderBy(_ => _, new GroupAuthorityComparer());
IComparable<T>
如果这是比较 Group
实例的唯一方法,您应该让它实现 IComparable<T>
,这样如果有人想对您的类进行排序,则不需要额外的代码:
class Group : IComparable<Group>
...
public int CompareTo(Group b)
if (b != null && (Id == 0 || b.Id == 0))
if (Id == b.Id)
// Mandatory as some sort algorithms require Compare(a, b) and Compare(b, a) to be consitent
return 0;
return Id == 0 ? -1 : 1;
return Comparer<string>.Default.Compare(Name, b.Name);
用法:
items.OrderBy(_ => _.Group);
应根据使用此特定比较器的位置来选择一种方式或另一种方式:是此类项目的主要排序还是仅应在一种特定情况下使用的排序,例如仅在一些管理视图。
您甚至可以更上一层并提供IComparable<GroupAuthority>
实现(一旦集团实现IComparable<Group>
就很容易):
class GroupAuthority : IComparable<GroupAuthority>
...
public int CompareTo(GroupAuthority b)
return Comparer<Group>.Default.Compare(Group, b.Group);
用法:
items.OrderBy(_ => _);
最后一个的优点是它会被自动使用,所以像GroupAuthoritys.ToList().Sort()
这样的代码会开箱即用。
【讨论】:
【参考方案2】:你可以试试这样的
list.Sort((x, y) =>
if (x.Id == 0)
return -1;
if (y.Id == 0)
return 1;
return x.Group.Name.CompareTo(y.Group.Name);
);
列表是List<T>
。
此方法利用List<T>
使用Comparison<T>
委托提供的自定义排序选项。
基本上这个方法的作用是,它只是在Id
时添加特殊的比较条件,如果它是零,它会返回一个值,表明对象更小,这使得对象进入列表的顶部。如果不是,它会使用其Group.Name
属性按升序对对象进行排序。
【讨论】:
这正在增加投票,我当然希望我能理解它。请解释一下。 @Blam 添加了解释,抱歉耽搁了。我是时候离开办公室了:( 我没有投反对票。我打算试试看。 @Blam 谢谢,我在发布之前进行了测试,如果有什么让我知道我会调查的。 这工作 +1。为什么你认为这个问题是-2?【参考方案3】: public IEnumerable<GroupAuthority> GroupAuthoritysSorted
get
return GroupAuthoritys.OrderBy(x => x.Group.ID == 0)
.ThenBy(x => x.Group.Name);
【讨论】:
以上是关于LINQ 自定义排序的主要内容,如果未能解决你的问题,请参考以下文章