C# 如何在Linq中的一行代码中对多个属性的列表进行排序
我想对多个属性的列表进行排序。我知道我可以用C# 如何在Linq中的一行代码中对多个属性的列表进行排序,c#,linq,sorting,C#,Linq,Sorting,我想对多个属性的列表进行排序。我知道我可以用 List<Order> l = source.OrderBy(c=> c.Property1).ThenBy(c=> c.Property2).ToList(); List l=source.OrderBy(c=>c.Property1).ThenBy(c=>c.Property2.ToList(); 然而,这只是为了提升。若我想对列表进行降序排序,我需要另一个代码 List<Order> l = source
List<Order> l = source.OrderBy(c=> c.Property1).ThenBy(c=> c.Property2).ToList();
List l=source.OrderBy(c=>c.Property1).ThenBy(c=>c.Property2.ToList();
然而,这只是为了提升。若我想对列表进行降序排序,我需要另一个代码
List<Order> l = source.OrderByDescending(c=> c.Property1).ThenByDescending(c=> c.Property2).ToList();
listl=source.OrderByDescending(c=>c.Property1)。然后是ByDescending(c=>c.Property2.ToList();
如果我想对属性1进行升序排序,对属性2进行降序排序,我必须使用
List<Order> l = source.OrderBy(c=> c.Property1).ThenByDescending(c=> c.Property2).ToList();
List l=source.OrderBy(c=>c.Property1),然后按降序(c=>c.Property2.ToList();
对于2个属性的排序,我需要4个不同的代码,对于3个属性,我需要9个不同的代码。没有好消息。我想知道是否有一种方法可以在一个代码中进行排序。谢谢 您可以编写自己的LINQ扩展来确定选择哪个方法。例如:
public static class LinqExtensions
{
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool ascending)
{
return ascending ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
}
}
该包提供了一个OrderBy扩展方法,该方法只接受一个字符串:
using System.Linq.Dynamic;
//...
var l = source.OrderBy("Property1 ascending, Property2 descending").ToList();
您可以使用它动态构建复杂的表达式:
string orderByClause = string.Format("Property1 {0}, Property2 {1}", "ascending", "descending");
var l = source.OrderBy(orderByClause).ToList();
如我在评论中所提到的,请参见项目Wiki中的更多信息,您可以创建如下内容
public static class LinqExtension
{
public static IOrderedEnumerable<TSource> OrderByAsc<TSource, TKey>(
this IEnumerable<TSource> source,
Expression<Func<T, object>> expression)
{
IEnumerable<TSource> newEnumerable = source;
int ctr = 0;
NewArrayExpression array = expression.Body as NewArrayExpression;
foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
{
if(ctr == 0)
newEnumerable = newEnumerable
.OrderBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
else
newEnumerable = newEnumerable
.ThenBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
ctr++;
}
return newEnumerable;
}
public static IOrderedEnumerable<TSource> OrderByDesc<TSource, TKey>(
this IEnumerable<TSource> source,
Expression<Func<T, object>> expression)
{
IEnumerable<TSource> newEnumerable = source;
NewArrayExpression array = expression.Body as NewArrayExpression;
int ctr = 0;
foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
{
if(ctr == 0)
newEnumerable = newEnumerable
.OrderByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
else
newEnumerable = newEnumerable
.ThenByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
ctr++;
}
return newEnumerable;
}
}
当然,您可以尝试创建一个扩展,将升序和降序合并到一个方法中。只是个主意
免责声明:我在记事本上写了这篇文章,由于缺乏资源,没有对它进行测试。这是最好的方法……您的意思是希望排序方向参数化吗,因此,相同的代码可以根据参数以升序和降序的任意组合进行排序?我认为linq应该提供一种排序方式,如:OrderBy(c=>c.Property1,sortOrder)。然后是By(c=>c.Property2,sortOrder)。它简单明了。Linq中有类似的东西吗?
对于2个属性的排序,我需要4个不同的代码
-我的意思是,是的,如果你硬编码每个可能的组合。就像从数组中读取100个元素一样,需要100行代码。概括您的需求,然后编写一个小方法,它将决定调用哪个order方法,以及调用哪个属性。@Stuart Whitehouse,是的,我想对参数化的排序,比如OrderBy(c=>c.Property1,sortOrder)。然后by(c=>c.Property2,sortOrder),其中sortOrder是bool。True表示上升,false表示下降。它简单明了。我认为Linq应该有类似的功能。如何做source.OrderBy(a=>a.Id,升序),然后是by(c=>c.name,降序)?我知道对不同属性的排序必须同时进行。@user585440您只需复制上面的代码,然后将其更改为ThenBy
。但是如何将OrderBy和ThenBy连接起来?@user585440我真的不知道您的意思。您可以使用与上述完全相同的方式编写重载,但要先更改为,然后再更改为。然后可以编写source.OrderBy(a=>a.Id,true),然后编写(a=>a.name,false)
对于然后按
,源类型为IOrderedQueryable
public static class LinqExtension
{
public static IOrderedEnumerable<TSource> OrderByAsc<TSource, TKey>(
this IEnumerable<TSource> source,
Expression<Func<T, object>> expression)
{
IEnumerable<TSource> newEnumerable = source;
int ctr = 0;
NewArrayExpression array = expression.Body as NewArrayExpression;
foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
{
if(ctr == 0)
newEnumerable = newEnumerable
.OrderBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
else
newEnumerable = newEnumerable
.ThenBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
ctr++;
}
return newEnumerable;
}
public static IOrderedEnumerable<TSource> OrderByDesc<TSource, TKey>(
this IEnumerable<TSource> source,
Expression<Func<T, object>> expression)
{
IEnumerable<TSource> newEnumerable = source;
NewArrayExpression array = expression.Body as NewArrayExpression;
int ctr = 0;
foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
{
if(ctr == 0)
newEnumerable = newEnumerable
.OrderByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
else
newEnumerable = newEnumerable
.ThenByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
ctr++;
}
return newEnumerable;
}
}
using myNameSpace.LinqExtensions;
...
l = l.OrderByAsc(item => new [] { item.Prop1, item.Prop2, item.Prop3});
l = l.OrderByDesc(item => new [] { item.Prop1, item.Prop2, item.Prop3});