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


77

我有一个给定参数“ 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;

如您所见,两个查询的区别仅在于“升序”。“下降”。我想合并两个查询,但是不知道如何合并。有人知道答案吗?


因此,您希望有一个查询可以根据布尔sortAsvending值进行升序或降序吗?那是对的吗。
内森·W

Answers:


119

您可以在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);

4
感谢您纠正我的愚蠢行为Marc :)(那是在午餐前发帖的问题...)
Jon Skeet

9
这个职位是回答和SO.com的两位名人编辑
Johnny_D

OrderByWithDirections之一不应该返回升序吗?
Ctrl_Alt_Defeat

1
@KOL:我不确定您的意思。如果你通过他们都将回到上升falsedescending
乔恩·斯基特

@JonSkeet,感谢您的解决方案,但我已经发布了有关其用法的问题。见:stackoverflow.com/questions/18348767/...
ekkis

42

就如何实现这一点而言,这会将方法从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的乘数。这仅对数字数据真正有用,但是是实现相同结果的一种轻松方式。


1
我正要写同样的话,然后我的VS冻结了:(
Nathan W

1
对于返回值int.MinValue,使用乘数也会失败。
乔恩·斯基特

为什么在linq查询中使用orderBy方法而不使用orderby关键字?
Joshit

@Joshit,因为在这两种情况下我需要执行不同的操作,与仅使用扩展方法相比,此处使用LINQ查询语法没有任何好处。如果您更喜欢查询语法:那就去做吧。
Marc Gravell

@MarcGravell非常感谢您的快速回复!!我认为,如果两个性能编程专家这样做的话,就值得问一下是否还有更深层次的原因;)
Joshit

8

怎样按所需属性订购desc,

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

然后做类似的事情

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

Reverse()是否太慢?


可能不是最优化的方法,但肯定是非常聪明的方法
Diego Penha

@DiegoPenha哼,但是如果在实现数据之前对实体使用linq应该是相同的,不是吗?我的意思是将相应地产生一个sql查询。你同意?
gsubiran

@DiegoPenha算了吧,LINQ到实体不支持.Reverse()函数😪
gsubiran

3

除了@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);
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.