在Linq OrderBy中使用自己的IComparer <T>
我有一个通用的
List<MyClass>
其中MyClass
有一个属性InvoiceNumber
,它包含如下的值:
一分之二十零万零九百零六
二分之二十零万零九百零六
..
十分之二十零万〇九百〇六
十一分之二十零万零九百零六
十二分之二十万○九百○六
我的清单是绑定到一个
BindingList<T>
它支持用linq进行sorting:
protected override void ApplySortCore( PropertyDescriptor property, ListSortDirection direction) { _sortProperty = property; _sortDirection = direction; var items = this.Items; switch (direction) { case ListSortDirection.Ascending: items = items.OrderByDescending(x => property.GetValue(x)).ToList(); break; case ListSortDirection.Descending: items = items.OrderByDescending(x => property.GetValue(x)).ToList(); break; } this.Items = items; }
然而,默认的比较器sorting(如假设)是这样的:
一分之二十零万零九百零六
十分之二十零万〇九百〇六
十一分之二十零万零九百零六
十二分之二十万○九百○六
二分之二十零万零九百零六
这在这种情况下是讨厌的。
现在我想用我自己的IComparer<T>
。 它看起来像这样:
public class MyComparer : IComparer<Object> { public int Compare(Object stringA, Object stringB) { String[] valueA = stringA.ToString().Split('/'); String[] valueB = stringB.ToString().Split('/'); if(valueA .Length != 2 || valueB .Length != 2) return String.Compare(stringA.ToString(), stringB.ToString()); if (valueA[0] == valueB[0]) { return String.Compare(valueA[1], valueB[1]); } else { return String.Compare(valueA[0], valueB[0]); } } }
并更改了ApplySortCore
代码以使用此IComparer
:
case ListSortDirection.Ascending: MyComparer comparer = new MyComparer(); items = items.OrderByDescending( x => property.GetValue(x), comparer).ToList(); break;
当我debugging我的代码时,我看到MyComparer.Compare(object, object)
被多次调用,并为比较方法返回正确的值(-1,0,1)。
但我的名单仍然是“错误的”方式。 我错过了什么吗? 我没有任何线索。
你的比较者看起来不对我。 你仍然只是在默认的文本sorting中sorting。 当然,你想要parsing这两个数字,并根据这个sorting:
public int Compare(Object stringA, Object stringB) { string[] valueA = stringA.ToString().Split('/'); string[] valueB = stringB.ToString().Split('/'); if (valueA.Length != 2 || valueB.Length != 2) { stringA.ToString().CompareTo(stringB.ToString())); } // Note: do error checking and consider i18n issues too :) if (valueA[0] == valueB[0]) { return int.Parse(valueA[1]).CompareTo(int.Parse(valueB[1])); } else { return int.Parse(valueA[0]).CompareTo(int.Parse(valueB[0])); } }
(请注意,这并不适合你的问题,说明你已经通过debugging,并validation了比较是返回正确的值 – 但我恐怕我怀疑在这方面的人为错误。)
此外,斯文的权利 – 改变items
的价值根本不会改变你的约束列表。 你应该添加:
this.Items = items;
在你的方法的底部。
我遇到了一般自然sorting的问题,并在这里写下了解决scheme:
自然sorting与Linq OrderBy()比较
您可以使用Alphanumalgorithm:
(...) items.OrderBy(x => property.GetValue(x), new AlphanumComparator()) (...)
哪里
AlphanumComparator是http://www.davekoelle.com/files/AlphanumComparator.cs
sorting列表只绑定到本地variables项目,而不绑定到绑定列表的Items属性,因此它仍然未sorting。
[编辑]基本上,你只是扔掉你的sorting努力的结果;-)
我们不能这样做:
public class MyComparer : IComparer<string> { public int Compare(string stringA, string stringB) { string small = stringA; string big = stringB; if (stringA.Length > stringB.Length) { small = stringB; big = stringA; } else if (stringA.Length < stringB.Length) { small = stringA; big = stringB; } for (int j = 0; j < small.Length; j++) { if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1; if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1; } //big is indeed bigger if (big.Length > small.Length) return 1; //finally they are smae return 0; } }
用法:
string[] inputStrings = {"_abc*&","#almnp","abc" }; //string[] inputStrings = { "#", "_", "_a", "@", "_" }; MyComparer computer = new MyComparer(); var kola = inputStrings.OrderBy(x => x, new MyComparer()).ToArray();
这与以下相同:
Array.Sort(inputStrings, StringComparer.Ordinal);