使用LINQ进行选择性排序,部分排序

时间:2010-02-17 15:26:27

标签: c# sorting union partial

假设我有一个对象列表:

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()Where()子句更优雅的方法:

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>对象。这就是我试图找到进行这种选择性排序的最佳方式的原因。

6 个答案:

答案 0 :(得分:7)

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

items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);

答案 1 :(得分:6)

正如迈克所提到的,在你的例子中,它会自动运行,但是我们想先得到所有-1个元素,然后按降序对剩余元素进行排序。这可以通过一个很好的技巧来完成。订购元素时可以使用多个键。第一个键可以是布尔值,对于所有-1值(因此它们将是第一个)将为false,对于所有其他值将为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;

它将首先生成n != -1false的所有值,然后使用n descending生成所有元素,以便获得:

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

一般情况下,当您需要处理某些元素时,尤其是在订购中,您只需要提供正确的订购密钥。

答案 2 :(得分:3)

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

然而,更一般地说,如果你仍然想对数据的子集应用不同的排序,我认为不会有更优雅的方式,因为这正是你正在做的事情,并且联合在逻辑上是准确的。你试图将两个单独的数据子集拉出来,对它们进行不同的排序,然后将它们合并在一起,这是我将要使用的东西之一。

答案 3 :(得分:1)

OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)

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

OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)

答案 4 :(得分:1)

这里也是一个自定义比较器,如果你想首先出现-1,但其余的是降序,但不知何故我发现它更优雅:)注意它是为int而制作的

class Comparer : IComparer<int>
{
  public int Compare(int x, int y)
  {
    if (x == -1 || y == -1) return x - y;
    return y - x;
  }
}

答案 5 :(得分:0)

使用custom comparer定义您想要的订单。

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());