【问题标题】:ascending/descending in LINQ - can one change the order via parameter?LINQ 中的升序/降序 - 可以通过参数更改顺序吗?
【发布时间】: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 值进行升序或降序操作?对吗?

标签: c# linq


【解决方案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,感谢您的解决方案,但我已经发布了一个关于其使用的问题。见:stackoverflow.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);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2012-09-02
    • 2016-12-30
    • 2012-04-18
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多