以下是我的收藏,以及数据:
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; }
}
预期结果(最终结果中词典的顺序)
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<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<T>:
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<T>
代码的使用:
foreach(OrderClause oc in orderClauseList)
{
NameSorter nSorter = new NameSorter();
nSorter.OC = oc;
data.Sort(nSorter);
}
IComparer代码无法像OrderBy
那样将结果链接起来,如何实现它。
答案 0 :(得分:2)
这是一个可用于链接比较器的类。它将接受一系列比较器,然后比较它使用每个比较器的每个项目,按顺序返回第一个非零比较的值,如果它们全部为零则返回零。
您可以使用它来获取您拥有的所有比较器并创建一个比较器,您可以将其传递给Sort
或您需要单个比较器的任何调用。
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);
}
}
另外,基于OrderBy
的方法可以重写为只迭代源序列一次,而不是三次,并且还避免了大量重复:
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]));
}