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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/388708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:33:48  来源:igfitidea点击:

ascending/descending in LINQ - can one change the order via parameter?

c#linq

提问by Johannes

I have a method which is given the parameter "bool sortAscending". Now I want to use LINQ to create sorted list depending on this parameter. I got then this:

我有一个方法,它被赋予参数“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;

As you can see, both queries differ only in "ascending" resp. "descending". I'd like to merge both queries, but I don't know how. Does anyone have the answer?

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

采纳答案by Jon Skeet

You can easily create your own extension method on IEnumerable or IQueryable:

您可以轻松地在 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);
}

Yes, you lose the ability to use a query expression here - but frankly I don't think you're actually benefiting from a query expression anyway in this case. Query expressions are great for complex things, but if you're only doing a single operation it's simpler to just put that one operation:

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

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

回答by Marc Gravell

In terms of how this is implemented, this changes the method- from OrderBy/ThenBy to OrderByDescending/ThenByDescending. However, you can apply the sort separately to the main query...

就如何实现而言,这改变了方法- 从 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);
}

Any use? You can create the entire "order" dynamically, but it is more involved...

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

Another trick (mainly appropriate to LINQ-to-Objects) is to use a multiplier, of -1/1. This is only really useful for numeric data, but is a cheeky way of achieving the same outcome.

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

回答by sports

What about ordering desc by the desired property,

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

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

And then doing something like

然后做类似的事情

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

Is it Reverse() too slow?

Reverse() 是不是太慢了?

回答by ehh

In addition to the beautiful solution given by @Jon Skeet, I also needed ThenBy and ThenByDescending, so I am adding it based on his solution:

除了@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);
    }