下面是我收集,以及数据:
Following is my collection, along with data:
var data = new List<Dictionary<object, object>>();
data.Add(new Dictionary<object, object>() {
{ "Firstname", "Bob"},
{ "Middlename", "Ack"},
{ "Lastname", "Banana"}
});
data.Add(new Dictionary<object, object>() {
{ "Firstname", "Amy"},
{ "Middlename", "Beck"},
{ "Lastname", "Apple"}
});
data.Add(new Dictionary<object, object>() {
{ "Firstname", "Charlie"},
{ "Middlename", "Emy"},
{ "Lastname", "Coconut"}
});
data.Add(new Dictionary<object, object>() {
{ "Firstname", "Andy"},
{ "Middlename", "Sob"},
{ "Lastname", "Apple"}
});
我要排序,使用下面的收集 OrderClause
的类:
List<OrderClause> orderClauseList = new List<OrderClause>()
{
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; }
}
预期结果(字典的最终结果顺序)
Expected Result (order of Dictionaries in final result)
Firstname: Charlie , Middlename: Emy , Lastname: Coconut
Firstname: Bob, Middlename: Ack, Lastname: Banana
Firstname: Amy, Middlename: Beck, Lastname: Apple
Firstname: Andy, Middlename: Sob, Lastname: Apple
随着使用排序依据
扩展方法做这项工作:
Following extension method using OrderBy
does the job:
public static List<Dictionary<object, object>> Sort(this
List<Dictionary<object, object>> data, List<OrderClause> 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<object, object>> 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&LT; T&GT;
class NameSorter : IComparer<Dictionary<object, object>>
{
public OrderClause OC { get; set;}
public int Compare( Dictionary<object, object> x, Dictionary<object, object> 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&LT; T&GT;
code:
foreach(OrderClause oc in orderClauseList)
{
NameSorter nSorter = new NameSorter();
nSorter.OC = oc;
data.Sort(nSorter);
}
的IComparer code是无法链结果为排序依据
为已完成,如何实现它。
IComparer code is not able to chain results as done by OrderBy
, how to achieve it.
下面是你可以用它来链comparers类。它将接受comparers的序列,然后进行比较,它使用每个comparers的每个项目中,为了,返回的第一非零比较的值,或零,如果它们都为零。
Here is a class that you can use to chain comparers. It will accept a sequence of comparers and then to compare each item it uses each of the comparers, in order, returning the value of the first non-zero comparison, or zero if they're all zero.
您可以使用此采取一切,你有comparers,创造任何你所需要的单一个比较器,你可以通过一个单一呼叫排序
或比较器的。
You can use this to take all of the comparers that you have and create a single comparer that you can pass to a single call to Sort
or whatever you need the single comparer for.
public class ComparerChain<T> : IComparer<T>
{
private IEnumerable<IComparer<T>> comparers;
public ComparerChain(IEnumerable<IComparer<T>> comparers)
{
this.comparers = comparers;
}
public int Compare(T x, T y)
{
return comparers.Select(comparer => comparer.Compare(x, y))
.FirstOrDefault(result => result != 0);
}
}
在一个侧面说明,你的排序依据
基础的方法可以被重新写入都只有迭代源序列一次,而是三次,还可以避免很多的复制:
On a side note, your OrderBy
based method can be re-written to both only iterate the source sequence once, instead of three times, and also avoid much of the duplication:
public static IEnumerable<Dictionary<object, object>> Sort(
this IEnumerable<Dictionary<object, object>> data,
IEnumerable<OrderClause> 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]));
}