选择排序与LINQ,偏序

问题描述 投票:5回答:6

比方说,我有对象的列表:

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>对象。这就是为什么我试图找到做这样的选择排序的最优化的方式。

c# sorting union partial
6个回答
7
投票

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

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

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;

它首先会产生针对n != -1false,然后所有元素使用n descending排序,这样你会得到所有的值:

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

当你需要处理尤其是在订货一些元素这个工作一般 - 你只需要提供正确的排序键。


3
投票

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

然而,更一般地,如果你仍然想不同的排序应用到数据的子集,我不认为会有一个更优雅的方式,因为这是你在做什么和工会在逻辑上是正确的。你想提取数据的两个不同的子集了,他们不同的排序,然后将它们合并在一起,这是对的事情我是工会要用于之一。


1
投票

另外这里,如果你想自定义比较-1到第一次出现,但其余的要降,但不知何故,我觉得它更优雅:)注意它是整数制作

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

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

或者,如果你需要按降序排序负值

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

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());
© www.soinside.com 2019 - 2024. All rights reserved.