LINQ 自定义排序 [英] LINQ Custom Sort

查看:33
本文介绍了LINQ 自定义排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个字母排序,但有一个例外.
有一个名称 = "Public" 且 ID = "0" 的组是我想要的.
(宁愿使用 ID = 0)
之后,然后按名称对其余部分进行排序.
这不会首先公开.

I want an alphabetic sort with one exception.
There is a Group with a Name = "Public" and an ID = "0" that I want first.
(would rather use ID = 0)
After that then sort the rest by Name.
This does not return public first.

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.

GroupAuthority has a public property Group and Group has Public properties ID and Name.

我基本上使用了公认的答案

I used basically the accepted answer

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;
        }
    }
}

推荐答案

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

You need to use a comparison function, they are functions that from two instances of your type return an integer that return 0 if both are equals, a negative value if the first is less than the second and a positive value if the first is greater than the second.

MSDN 有一个漂亮的表格,更容易理解比文本(StackOverflow 在 2014 年仍然不支持表格)

MSDN has a nice table that is easier to follow than text (StackOverflow still doesn't support tables in 2014)

大多数排序方法都接受 IComparer< 类型的自定义比较器实现;T> 你应该创建一个封装 Group 的自定义规则:

Most sort methods accept a custom comparer implementation of type IComparer<T> you should create one encapsulating your custom rules for 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());



如果这是比较 Group 实例的唯一方法,你应该让它实现 IComparable 这样如果有人想对你的班级进行排序,就不需要额外的代码:

If it is the only way to compare Group instances you should make it implement IComparable<T> so that no aditional code is needed if anyone want to sort your class :

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);

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

The choice between one way or the other should be done depending on where this specific comparer is used: Is it the main ordering for this type of item or just the ordering that should be used in one specific case, for example only in some administrative view.

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

You can even go one level up and provide an IComparable<GroupAuthority> implementation (It's easy once Group implement IComparable<Group>):

class GroupAuthority : IComparable<GroupAuthority>
{
    ...

    public int CompareTo(GroupAuthority b)
    {
        return Comparer<Group>.Default.Compare(Group, b.Group);
    }
}

用法:

items.OrderBy(_ => _);

最后一个的优点是它会被自动使用,所以像这样的代码:GroupAuthoritys.ToList().Sort() 会开箱即用.

The advantage of the last one is that it will be used automatically, so code like: GroupAuthoritys.ToList().Sort() will do the correct thing out of the box.

这篇关于LINQ 自定义排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆