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

发布于 2024-08-21 21:15:44 字数 892 浏览 9 评论 0原文

假设我有一个对象列表:

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 }
};

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

Let's say I have a list of objects:

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

I need to order it so that items with Order > -1 be on top of the list ordered by Order ascending, and remaining items with Order == -1 were following them.

Is there a more elegant way of doing this than using Conact() and Where() clauses:

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

So that after sorting this list would look like:

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

Also items list in actual scenario is already a complex IQueryable<T> object. That's why I am trying to find the most optimal way of doing such selective ordering.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

时光匆匆的小流年 2024-08-28 21:15:44

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

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

You could try this - it produces the result you expect:

items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);
失去的东西太少 2024-08-28 21:15:44

正如迈克提到的,在您的示例中,它会自动工作,但假设我们希望首先获取所有 -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 降序 对所有元素进行排序,这样您就可以你会得到:

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

当您需要处理某些元素(尤其是排序中的元素)时,这通常是有效的 - 您只需要提供正确的排序键即可。

As Mike mentioned, in your example, it would work automatically, but say we wanted to get all -1 elements first and then sort remaining elements in a descending order. This can be done using a nice trick. You can use multiple keys when ordering elements. The first key can be a Boolean value which will be false for all -1 values (so they will be first) and true for all other values (so they won't be reordered). The second key can be whatever you want to order the remaining elements. For example:

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

It will first yield all values for which n != -1 is false and then all elements ordered using n descending so you'll get:

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

This works in general when you need to handle some elements especially in the ordering - you just need to provide the right ordering keys.

冷情妓 2024-08-28 21:15:44

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

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

If you order by ascending, -1 should already be at the top of the list, because it is the smallest value.

However, more generally, if you still wanted to apply different sorting to subsets of the data, I don't think there would be a more elegant way, because that's exactly what you are doing and the union is logically accurate. You're trying to pull two seperate subset of the data out, sort them differently, and then merge them together, which is one of the things what I union is to be used for.

遮云壑 2024-08-28 21:15:44

如果您希望 -1 首先出现,但其余的为 降序 ,那么这里还有一个自定义比较器,但不知怎的,我发现它更优雅:)注意它是为整数而设计的

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

Also a custom comparer here if you want -1 to appear first, but the rest to be descending , but somehow I find it more elegant :) Note it's made for ints

class Comparer : IComparer<int>
{
  public int Compare(int x, int y)
  {
    if (x == -1 || y == -1) return x - y;
    return y - x;
  }
}
不喜欢何必死缠烂打 2024-08-28 21:15:44
OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)

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

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

or if you need to order the negative values in descending order

OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)
若沐 2024-08-28 21:15:44

使用自定义比较器来定义所需的顺序。

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

Use a custom comparer to define the order you want.

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

Then you could do:

var orderedItems = items.OrderBy(x => x.Order, new MyComparer());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文