5

假设我有一个对象列表:

var items = new {
    new { Order = 0 },
    new { Order = 1 },
    new { Order = -1 },
    new { Order = 3 },
    new { Order = 2 },
    new { Order = -1 }
};

我需要对其进行排序,以便Order > -1在按顺序升序排序的列表顶部的项目,而其余项目Order == -1则跟随它们。

Conact()有没有比使用andWhere()子句更优雅的方法:

var orderedItems = items.Where(x => x.Order > -1).OrderBy(x => x.Order)
                   .Conact(items.Where(x => x.Order == -1);

因此,在排序此列表后将如下所示:

var items = new {
    new { Order = 0 },
    new { Order = 1 },
    new { Order = 2 },
    new { Order = 3 },
    new { Order = -1 },
    new { Order = -1 }
};

实际场景中的列表也items已经是一个复杂的IQueryable<T>对象。这就是为什么我试图找到进行这种选择性排序的最佳方式。

4

6 回答 6

7

你可以试试这个——它会产生你期望的结果:

items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);
于 2010-02-17T15:41:54.867 回答
6

正如迈克所提到的,在您的示例中,它会自动工作,但假设我们希望首先获取所有 -1 元素,然后按降序对剩余元素进行排序。这可以使用一个不错的技巧来完成。订购元素时可以使用多个键。第一个键可以是一个布尔值,它将false用于所有 -1 值(因此它们将是第一个)和true所有其他值(因此它们不会被重新排序)。第二个键可以是您想要订购剩余元素的任何内容。例如:

var nums = new int[] { -1, 4, 2, 3, -1, 4, 7 };
var q = from n in nums
        orderby n != -1, n descending
        select n;

它将首先产生 is 的所有值,n != -1然后是false使用排序的所有元素,n descending因此您将获得:

-1, -1, 7, 4, 4, 3, 2

当您需要处理一些元素时,尤其是在排序中,这通常会起作用——您只需要提供正确的排序键。

于 2010-02-17T15:35:59.053 回答
3

如果按升序排序,-1 应该已经在列表的顶部,因为它是最小值。

但是,更一般地说,如果您仍然想对数据子集应用不同的排序,我认为不会有更优雅的方式,因为这正是您正在做的,并且联合在逻辑上是准确的。您正在尝试提取两个单独的数据子集,对它们进行不同的排序,然后将它们合并在一起,这是我联合的用途之一。

于 2010-02-17T15:31:18.680 回答
1
OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)

或者如果您需要按降序排列负值

OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)
于 2010-02-17T15:37:29.800 回答
1

如果您希望 -1 首先出现,那么这里还有一个自定义比较器,但其余的是降序,但不知何故我觉得它更优雅:) 请注意它是为 ints 制作的

class Comparer : IComparer<int>
{
  public int Compare(int x, int y)
  {
    if (x == -1 || y == -1) return x - y;
    return y - x;
  }
}
于 2010-02-17T15:43:21.310 回答
0

使用自定义比较器来定义您想要的顺序。

public class MyComparer : IComparer<int>
{
    public int Compare(int a, int b)
    {
        if ((a < 0) && (b >= 0))
        {
            return 1;
        }
        if ((a >= 0) && (b < 0))
        {
            return -1;
        }
        return int.Compare(a, b);
    }
}

然后你可以这样做:

var orderedItems = items.OrderBy(x => x.Order, new MyComparer());
于 2010-02-17T15:35:53.250 回答