【问题标题】:Conditional "orderby" sort order in LINQLINQ 中的条件“orderby”排序顺序
【发布时间】:2009-10-22 10:59:44
【问题描述】:

在 LINQ 中,是否可以按排序顺序(升序与降序)进行条件排序。

类似这样的东西(无效代码):

bool flag;

(from w in widgets
 where w.Name.Contains("xyz")
 orderby w.Id (flag ? ascending : descending)
 select w)

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    如果您以增量方式构建表达式,则可以这样做。通常使用表达式比使用理解表达式更容易:

    var x = widgets.Where(w => w.Name.Contains("xyz"));
    if (flag) {
      x = x.OrderBy(w => w.property);
    } else {
      x = x.OrderByDescending(w => w.property);
    }
    

    (假设小部件的 property 是排序的基础,因为您没有列出一个。)

    【讨论】:

    • 如果需要或不需要,如何在动态条件下进行多次订购。
    • 只需要对OrderByThenBy的结果使用不同的变量来保持不同的返回类型;否则只需添加对适用的ThenByThenByDescending LINQ 运算符的调用。
    【解决方案2】:

    ...或者在一个语句中完成所有操作

    bool flag;
    
    var result = from w in widgets where w.Name.Contains("xyz")
      orderby
        flag ? w.Id : 0,
        flag ? 0 : w.Id descending
      select w;
    

    【讨论】:

    • 如果底层数据在 SQL 中,这个答案似乎最有可能使用 SQL 的 ORDERBY 子句,但我不知道事实。
    【解决方案3】:

    这是一个更通用的解决方案,可用于各种条件 lambda 表达式,而不会破坏表达式的流程。

    public static IEnumerable<T> IfThenElse<T>(
        this IEnumerable<T> elements,
        Func<bool> condition,
        Func<IEnumerable<T>, IEnumerable<T>> thenPath,
        Func<IEnumerable<T>, IEnumerable<T>> elsePath)
    {
        return condition()
            ? thenPath(elements)
            : elsePath(elements);
    }
    

    例如

    var result = widgets
        .Where(w => w.Name.Contains("xyz"))
        .IfThenElse(
            () => flag,
            e => e.OrderBy(w => w.Id),
            e => e.OrderByDescending(w => w.Id));
    

    【讨论】:

    • 这太棒了!您可以修改它以使elsePath 成为可选参数
    • 您可以简单地将e =&gt; e 用于elsePath,枚举将按原样返回。
    • 这很不错,但是我做了一个更改,因为 IEnumerable 强制从数据库中检索项目,所以我使用 IQueryable 而不是 IEnumerable。
    【解决方案4】:

    您可以定义一个没有排序的基本查询,然后根据标志排序:

    var query=(from w in widgets
      where w.Name.Contains("xyz")
      select w);
    
    var result = flag ?
      query.OrderBy(w =>w) :
      query.OrderByDescending(w = w);
    

    【讨论】:

      【解决方案5】:

      您可以尝试以下方法:

      var q = from i in list
               where i.Name = "name"
               select i;
      if(foo)
           q = q.OrderBy(o=>o.Name);
      else
           q = q.OrderByDescending(o=>o.Name);
      

      【讨论】:

        【解决方案6】:

        如果排序属性Id 是一个数字(或支持一元减号),也可以这样做:

        bool ascending = ...
        
        collection.Where(x => ...)
          .OrderBy(x => ascending ? x.Id : -x.Id)
          .Select(x => ...)
        
        // LINQ query
        from x in ...
        orderby (ascending ? x.Id : -x.Id)
        select ...
        

        【讨论】:

          【解决方案7】:

          MoreLINQ NuGet package 还提供了扩展方法,使this 更方便。 它还提供了更多有用的扩展方法,因此在我的项目中是一个稳定的选择。

          【讨论】:

            【解决方案8】:

            您甚至可以进行更复杂的排序并保持简短:

                var dict = new Dictionary<int, string>() { [1] = "z", [3] = "b", [2] = "c" };
                var condition =  true;
                var result = (condition ? dict.OrderBy(x => x.Key) : dict.OrderByDescending(x => x.Value))
                    .Select(x => x.Value);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多