LINQ 中的升序/降序 - 可以通过参数更改顺序吗?

Posted

技术标签:

【中文标题】LINQ 中的升序/降序 - 可以通过参数更改顺序吗?【英文标题】:ascending/descending in LINQ - can one change the order via parameter? 【发布时间】:2008-12-23 11:52:58 【问题描述】:

我有一个方法,它的参数是“bool sortAscending”。现在我想使用 LINQ 根据这个参数创建排序列表。然后我得到了这个:

var ascendingQuery = from data in dataList
                      orderby data.Property ascending
                      select data;

var descendingQuery = from data in dataList
                      orderby data.Property descending
                      select data;

如您所见,这两个查询仅在“升序”方面有所不同。 “下降”。我想合并这两个查询,但我不知道如何。有人知道答案吗?

【问题讨论】:

所以您希望有一个查询可以根据 bool sortAsvending 值进行升序或降序操作?对吗? 【参考方案1】:

您可以轻松地在 IEnumerable 或 IQueryable 上创建自己的扩展方法:

public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource,TKey>
    (this IEnumerable<TSource> source,
     Func<TSource, TKey> keySelector,
     bool descending)

    return descending ? source.OrderByDescending(keySelector)
                      : source.OrderBy(keySelector);


public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey>
    (this IQueryable<TSource> source,
     Expression<Func<TSource, TKey>> keySelector,
     bool descending)

    return descending ? source.OrderByDescending(keySelector)
                      : source.OrderBy(keySelector);

是的,您在这里失去了使用查询表达式的能力 - 但坦率地说,在这种情况下,我认为您实际上并没有从查询表达式中受益。查询表达式非常适合复杂的事情,但如果你只做一个操作,那么只做一个操作会更简单:

var query = dataList.OrderByWithDirection(x => x.Property, direction);

【讨论】:

感谢 Marc 纠正我的愚蠢 :) (这就是在午餐前发帖的问题......) 此帖由 SO.com 的两位名人回答和编辑 OrderByWithDirections 之一不应该返回升序吗? @KOL:我不确定你的意思。如果您将false 传递给descending,它们都会升序返回。 @JonSkeet,感谢您的解决方案,但我已经发布了一个关于其使用的问题。见:***.com/questions/18348767/…【参考方案2】:

就如何实现而言,这改变了方法 - 从 OrderBy/ThenBy 到 OrderByDescending/ThenByDescending。但是,您可以将排序单独应用于主查询...

var qry = from .... // or just dataList.AsEnumerable()/AsQueryable()

if(sortAscending) 
    qry = qry.OrderBy(x=>x.Property);
 else 
    qry = qry.OrderByDescending(x=>x.Property);

有用吗?您可以动态创建整个“订单”,但涉及更多...

另一个技巧(主要适用于 LINQ-to-Objects)是使用 -1/1 的乘数。这仅对数字数据真正有用,但这是实现相同结果的一种厚颜无耻的方式。

【讨论】:

我正要写这个完全相同的东西然后我的 VS 冻结了:( 对于 int.MinValue 的返回值,使用乘数也会失败。 为什么在 linq-query 中使用 orderBy 方法而不是 orderby 关键字? @Joshit 因为我需要在这两种情况下执行不同的操作,并且在这里使用 LINQ 查询语法与仅使用扩展方法相比没有任何好处。如果您更喜欢查询语法:去做,就可以了。 @MarcGravell 非常感谢您的快速回复!我想,如果两个性能编程的杰出人物这样做,那么值得一问是否有更深层次的原因;)【参考方案3】:

按所需属性排序 desc 怎么样,

   blah = blah.OrderByDescending(x => x.Property);

然后做类似的事情

  if (!descending)
  
       blah = blah.Reverse()
  
  else
  
      // Already sorted desc ;)
  

Reverse() 是不是太慢了?

【讨论】:

可能不是最优化的,但肯定是一个非常聪明的方法 @DiegoPenha 嗯,但万一它在物化数据之前对实体的 linq 应该是相同的,不是吗?我的意思是会相应地生成一个 sql 查询。你同意吗? @DiegoPenha 算了,linq to entity 不支持 .Reverse() 函数?【参考方案4】:

除了@Jon Skeet 给出的漂亮解决方案,我还需要 ThenBy 和 ThenByDescending,所以我根据他的解决方案添加它:

    public static IOrderedEnumerable<TSource> ThenByWithDirection<TSource, TKey>(
         this IOrderedEnumerable<TSource> source, 
         Func<TSource, TKey> keySelector,  
         bool descending)
    
        return descending ? 
               source.ThenByDescending(keySelector) :
               source.ThenBy(keySelector);
    

【讨论】:

以上是关于LINQ 中的升序/降序 - 可以通过参数更改顺序吗?的主要内容,如果未能解决你的问题,请参考以下文章

C# LINQ 匿名类 动态排序

Linq 对string[]字符串数组进行排序 (升序降序乱序)

lambda linq 表达式 ListBox 的升序 降序 乱序

Linq 基本操作

JavaScript sort函数的使用

js数组排序的六种方法