使用IComparer而不是OrderBy对Dictionary进行排序

以下是我的collections,以及数据:

var data = new List<Dictionary>(); data.Add(new Dictionary() { { "Firstname", "Bob"}, { "Middlename", "Ack"}, { "Lastname", "Banana"} }); data.Add(new Dictionary() { { "Firstname", "Amy"}, { "Middlename", "Beck"}, { "Lastname", "Apple"} }); data.Add(new Dictionary() { { "Firstname", "Charlie"}, { "Middlename", "Emy"}, { "Lastname", "Coconut"} }); data.Add(new Dictionary() { { "Firstname", "Andy"}, { "Middlename", "Sob"}, { "Lastname", "Apple"} }); 

我想使用以下OrderClause类集合对其进行排序:

 List orderClauseList = new List() { new OrderClause(){ColumnName = "Lastname", IsAscending = false}, new OrderClause(){ColumnName = "Middlename", IsAscending = true}, new OrderClause(){ColumnName = "Firstname", IsAscending = true} }; public class OrderClause { public string ColumnName { get; set; } public bool IsAscending { get; set; } } 

预期结果(最终结果中的词典顺序)

 Firstname: Charlie , Middlename: Emy , Lastname: Coconut Firstname: Bob, Middlename: Ack, Lastname: Banana Firstname: Amy, Middlename: Beck, Lastname: Apple Firstname: Andy, Middlename: Sob, Lastname: Apple 

使用OrderBy以下扩展方法完成了这项工作:

  public static List<Dictionary> Sort(this List<Dictionary> data, List orderClauseList) { // If OrderBy collection is empty, then return original collection if (orderClauseList == null || !orderClauseList.Any()) return data; // First one is OrderBy or OrderByDescending. var orderClauseFirst = orderClauseList.First(); IOrderedEnumerable<Dictionary> ordered = (orderClauseFirst.IsAscending) ? data.OrderBy(d => d[orderClauseFirst.ColumnName]) : data.OrderByDescending(d => d[orderClauseFirst.ColumnName]); // Second element onwards it is thenBy or ThenByDescending ordered = orderClauseList.Skip(1) // Skip first element as its already processed .Aggregate(ordered, (current, orderClause) => (orderClause.IsAscending) ? current.ThenBy(d => d[orderClause.ColumnName]) : current.ThenByDescending(d => d[orderClause.ColumnName])); return ordered.ToList(); } 

但是,使用以下IComparer:我无法获得正确的结果IComparer:

 class NameSorter : IComparer<Dictionary> { public OrderClause OC { get; set;} public int Compare( Dictionary x, Dictionary y ) { int retVal = 0; if(OC.IsAscending) retVal = string.Compare(x[OC.ColumnName].ToString(),y[OC.ColumnName].ToString()); else retVal = string.Compare(y[OC.ColumnName].ToString(),x[OC.ColumnName].ToString()); return retVal; } } 

以下是IComparer代码的用法:

 foreach(OrderClause oc in orderClauseList) { NameSorter nSorter = new NameSorter(); nSorter.OC = oc; data.Sort(nSorter); } 

IComparer代码无法像OrderBy那样链接​​结果,如何实现它。

这是一个可用于链式比较器的类。 它将接受一系列比较器,然后比较它使用每个比较器的每个项目,按顺序返回第一个非零比较的值,如果它们全部为零则返回零。

您可以使用它来获取您拥有的所有比较器并创建一个比较器,您可以将其传递给Sort的单个调用或您需要单个比较器的任何内容。

 public class ComparerChain : IComparer { private IEnumerable> comparers; public ComparerChain(IEnumerable> comparers) { this.comparers = comparers; } public int Compare(T x, T y) { return comparers.Select(comparer => comparer.Compare(x, y)) .FirstOrDefault(result => result != 0); } } 

另外,基于OrderBy的方法可以重写为只迭代源序列一次,而不是三次,并且还避免了大量重复:

 public static IEnumerable> Sort( this IEnumerable> data, IEnumerable orderClauseList) { var ordered = data.OrderBy(_ => 1); return orderClauseList.Aggregate(ordered, (current, orderClause) => (orderClause.IsAscending) ? current.ThenBy(d => d[orderClause.ColumnName]) : current.ThenByDescending(d => d[orderClause.ColumnName])); }