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

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

问题描述

我要一个字母的排序有一个例外。结果
有一组与NAME =公共和ID =0,我想先。结果
(宁可使用ID = 0)结果
之后,则可以按名称的其余部分。结果
这不返回首次公开。

 公开的IEnumerable< GroupAuthority> GroupAuthoritysSorted 
{
得到
{
返回GroupAuthoritys.OrderBy(X => x.Group.Name);
}
}



我要的是:



 返回GroupAuthoritys.Where(X => x.ID == 0)
UNION
GroupAuthoritys.Where(X => ; x.ID大于0).OrderBy(X => x.Group.Name);



GroupAuthority有一个公共财产集团和集团拥有公共属性ID和名称。



我基本上都采用公认的答案

 使用System.ComponentModel; 

命名空间SortCustom
{
公共部分类主窗口:窗口
{
公共主窗口()
{
的InitializeComponent() ;
TestSort();
}
私人无效TestSort()
{
名单,LT; CustomSort> LCS =新的List< CustomSort>();
LCS.Add(新CustomSort(5,SSS));
LCS.Add(新CustomSort(6,XXX));
LCS.Add(新CustomSort(4,XXX));
LCS.Add(新CustomSort(3,AAA));
LCS.Add(新CustomSort(7,BBB));
LCS.Add(新CustomSort(0,酒吧));
LCS.Add(新CustomSort(2,EEE));
LCS.Add(新CustomSort(3,WWW));
的foreach(CustomSort CS在LCS)System.Diagnostics.Debug.WriteLine(cs.Name);
LCS.Sort();
的foreach(CustomSort CS在LCS)System.Diagnostics.Debug.WriteLine(cs.Name);
}
}
公共类CustomSort:对象,INotifyPropertyChanged的,IComparable的< CustomSort>
{
公共事件PropertyChangedEventHandler的PropertyChanged;
公共无效OnPropertyChanged(PropertyChangedEventArgs E)
{
如果(的PropertyChanged!= NULL)的PropertyChanged(这一点,E);
}
私人Int16的ID;
私人字符串名称;
公众的Int16 ID {{返回ID; }}
公共字符串名称{{返回名称; }}
公众诠释的CompareTo(CustomSort OBJ)
{
如果(this.ID == 0)返回-1;
如果(OBJ == NULL)回报1;
如果(obj是CustomSort)
{
CustomSort补偿=(CustomSort)目标文件;
如果(comp.ID == 0)返回1;
返回的String.Compare(this.Name,comp.Name,真正的);
}
,否则
{
返回1;
}
}
公众覆盖布尔等于(obj对象)
{
//检查空值和比较运行时类型。
如果(OBJ == NULL)返回false;
如果((obj是CustomSort)!)返回false;
CustomSort补偿=(CustomSort)目标文件;
回报率(comp.ID == this.ID);
}
公共覆盖INT的GetHashCode()
{
回报(Int32)已ID;
}
公共CustomSort(Int16的ID,字符串名称)
{
ID = ID;
NAME =名称;
}
}
}


解决方案

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



MSDN具有好的表更易于跟踪非文本(计算器仍然不支持在2014年的表)



的IComparer< T>



大多数的排序方法接受类型的自定义比较实施的 的IComparer< T> 你应该创建一个封装定制

 类GroupComparer适合:规则;组> IComparer的< 
{
公众诠释比较(A组,B组)
{
如果(A = NULL&放大器;!和b = NULL&放大器;!及(a.Id == 0 || b.Id == 0))
{
如果(a.Id == b.Id)
{
//强制性的,因为某种算法要求比较(A,b)和比较(b,A)是consitent
返回0;
}
返回A.ID == 0? -1:1;
}

如果(A == NULL || b == NULL)
{
如果(的ReferenceEquals(A,B))
$ { b $ b返回0;
}
返回== NULL? -1:1;
}
返回的Comparer<串GT; .Default.Compare(a.Name,b.Name);
}
}



用法:

  items.OrderBy(_ => _,新GroupAuthorityComparer()); 







< H1> IComparable的< T>

如果它是比较集团<的唯一途径/ code>情况下,你应该让执行 IComparable的< T> 所以,如果有人要排序类不需要aditional的代码:

 类组:IComparable的<组> 
{
...

公众诠释的CompareTo(B组)
{
如果(B = NULL&放大器;!及(编号== 0 || b.Id == 0))
{
如果(编号== b.Id)
{
//强制性的,因为某种算法需要比较(一, b)和比较(b,A)是consitent
返回0;
}
返回标识== 0? -1:1;
}

返回的Comparer<串GT; .Default.Compare(名称,b.Name);
}
}



用法:

  items.OrderBy(_ => _.Group); 

的一种方式或其他应视在使用这个特定的比较器来完成之间的选择:是它的主要排序为这种类型的项目或只是排序的应在一个特定的情况下,只有在某些管理视图中使用,例如



可以甚至走一提升等级,并提供了一​​个 IComparable的< GroupAuthority> 实施(它曾经集团实现很容易 IComparable的<组>

 类GroupAuthority:IComparable的< GroupAuthority> 
{
...

公众诠释的CompareTo(GroupAuthority B)
{
返回的Comparer<组> .Default.Compare(组,B。组);
}
}



用法:

  items.OrderBy(_ => _); 



最后一项的优点是,它会自动使用,因此这样的代码: GroupAuthoritys.ToList()排序()会做正确的事情开箱。


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

What I want is:

return GroupAuthoritys.Where(x => x.ID == 0)
       UNION 
       GroupAuthoritys.Where(x => x.ID > 0).OrderBy(x => x.Group.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;
        }
    }
}

解决方案

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 has a nice table that is easier to follow than text (StackOverflow still doesn't support tables in 2014)

IComparer<T>

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

Usage:

items.OrderBy(_ => _, new GroupAuthorityComparer());



IComparable<T>

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

Usage:

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.

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

Usage:

items.OrderBy(_ => _);

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天全站免登陆