LINQ自定义排序

pap*_*zzo 4 c# linq sorting

我想要一个字母排序,但有一个例外.
有一个名为"公共"的组和一个我想要的ID ="0"的组.
(宁可使用ID = 0)
然后按名称对其余部分进行排序.
这不会首先返回公众.

public IEnumerable<GroupAuthority> GroupAuthoritysSorted 
{ 
   get 
   { 
       return GroupAuthoritys.OrderBy(x => x.Group.Name); 
   } 
}
Run Code Online (Sandbox Code Playgroud)

我想要的是:

return GroupAuthoritys.Where(x => x.ID == 0)
       UNION 
       GroupAuthoritys.Where(x => x.ID > 0).OrderBy(x => x.Group.Name);
Run Code Online (Sandbox Code Playgroud)

GroupAuthority具有公共属性Group和Group具有公共属性ID和名称.

我基本上使用了接受的答案

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jul*_*lia 13

您需要使用比较函数,它们是来自您的类型的两个实例的函数返回一个整数,如果两者都是等于则返回0,如果第一个小于第二个则返回负值,如果第一个小于第二个则返回正值第二.

MSDN有一个很好的表比文本更容易遵循(StackOverflow在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

items.OrderBy(_ => _, new GroupAuthorityComparer());
Run Code Online (Sandbox Code Playgroud)



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);
    }   
}
Run Code Online (Sandbox Code Playgroud)

用法:

items.OrderBy(_ => _.Group);
Run Code Online (Sandbox Code Playgroud)

应该根据使用此特定比较器的位置来完成这种或那种方式之间的选择:它是此类项目的主要排序还是仅在一个特定情况下应使用的排序,例如仅在某些管理视图中.

您甚至可以升级一级并提供IComparable<GroupAuthority>实现(一旦实现Group就很容易IComparable<Group>):

class GroupAuthority : IComparable<GroupAuthority>
{
    ...

    public int CompareTo(GroupAuthority b)
    {
        return Comparer<Group>.Default.Compare(Group, b.Group);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

items.OrderBy(_ => _);
Run Code Online (Sandbox Code Playgroud)

最后一个的优点是它将被自动使用,因此代码如下:GroupAuthoritys.ToList().Sort()将开箱即用.


Sri*_*vel 8

你可以尝试这样的事情

list.Sort((x, y) =>
{
    if (x.Id == 0)
    {
        return -1;
    }
    if (y.Id == 0)
    {
        return 1;
    }

    return x.Group.Name.CompareTo(y.Group.Name);
});
Run Code Online (Sandbox Code Playgroud)

列表在哪里List<T>.

此方法利用List<T>使用Comparison<T>委托提供的自定义排序选项.

基本上这个方法的作用是,它只是添加特殊条件进行比较时Id,如果它为零,它将返回一个值,表示对象较小,使对象进入列表的顶部.如果不是,则使用其Group.Name属性按升序对对象进行排序.