【问题标题】:C# LINQ Orderby - How does true/false affect orderby?C# LINQ Orderby - 真/假如何影响 orderby?
【发布时间】:2016-12-29 20:31:27
【问题描述】:

我正在研究一些 LINQ 排序,因为我有一个 Id 列表,我需要按顺序对它们进行排序。但是,某些 id 需要优先于标准排序。

鉴于此 C# 代码(可以粘贴到 .NET Fiddle 中进行测试),排序按我的需要工作,但我不明白为什么 contains 上的 not (!) 运算符给了我顺序正确吗?

我的预期排序输出是 (5, 1, 2, 3, 4, 6, 7, 8, 9)。

如果我的订单中有Contains,它不应该为返回true 的行提供排序优先级吗?相反,它似乎为返回 false 的行提供了排序优先级。

using System.Linq;
using System;

public class Program
{
  public static void Main()
  {
    var numbersToFilterBy = new [] {5, 11, 20};

    var x = new [] {new XClass(){Id = 1}, new XClass(){Id = 9}, new XClass(){Id = 5}, new XClass(){Id = 3}, new XClass(){Id = 4}, new XClass(){Id = 2}, new XClass(){Id = 6}, new XClass(){Id = 8}, new XClass(){Id = 7}};

    var trueData = (from data in x
                   orderby !numbersToFilterBy.Contains(data.Id), data.Id
                    select data).ToList();

    foreach(var item in trueData){
        Console.WriteLine(item.Id);
  }
}

public class XClass{
    public int Id{get;set;}
  }
}

为什么会发生这种情况的解释是什么?

【问题讨论】:

    标签: c# .net linq sorting operators


    【解决方案1】:

    让我以List<bool> 为例进行解释。考虑以下 sn-p:

    List<bool> BoolList = new List<bool>() { true, false, false, true };
    var opList = BoolList.OrderBy(x => x).ToList();
    

    最后,opList 的值将是 false,false,true,true,这意味着当我们在布尔值列表上应用 OrderBy 时,首先出现 false。这是因为 false 被视为 0 而 true 将被视为 1

    在您的情况下,列表首先根据orderby !numbersToFilterBy.Contains(data.Id) 排序为5,1,9,3,4,2,6,8,7,然后data.Id 将为您提供5, 1, 2, 3, 4, 6, 7, 8, 9 的确切结果。

    如果你从OrderBy 中删除!,它会给你像1,9,3,4,2,6,8,7,5 这样的第一个排序结果,因为5 的条件为真,因此它将在排序中排在最后。

    【讨论】:

    • 正如我在另一个答案中所说,false 永远不会被认为是 0 和 true 1。它的结果与它们相同,但实际上只是它们定义了两个布尔值的排序。这可能是吹毛求疵,但暗示框架可能会将布尔值转换为整数是误导性的,并且并不比他们刚刚定义排序的真实陈述更简单。如果人们习惯于在布尔值和数值之间进行转换的语言,这可能会帮助人们记住顺序。
    【解决方案2】:

    OrderBy 方法将默认按升序对项目进行排序。现在,假设布尔值的数字表示是:

    • false = 0
    • true = 1

    false 值自然会排在第一位。如果您想颠倒顺序,只需使用descending 关键字:

    var trueData = (from data in x
                   orderby numbersToFilterBy.Contains(data.Id) descending, data.Id
                    select data).ToList();
    

    【讨论】:

    • 在 c# 中,布尔值没有数字表示。它们不是我们假装是布尔值的幕后数字,它们只是布尔值。话虽如此,这种逻辑可以很好地帮助人们记住排序是如何工作的(并且很可能就是为什么 .net 的设计是这样的),但值得记住的是,在 .net 中没有 bool 的数字表示。跨度>
    • @Chris 但是,如果将布尔值转换为整数,则会出现数字结果。这仍然比其他一些语言更多。
    • @SebastianSchulz:这与布尔值是整数不同。所有CompareTo 方法都返回一个整数。它只是比较的工作方式。有关更多详细信息,请参阅msdn.microsoft.com/en-us/library/…,但基本上 0 表示它们相等,负表示实例位于参数之前,正表示实例位于参数之后。 CompareTo 的结果表示顺序,在排序时不使用它(即它不按 CompareTo 的结果排序,这听起来像是你可能建议的)。
    • @Chris Convert.ToInt32(Boolean)false 转换为 0true 转换为 1
    • @JeanHominal:这是真的,但该方法中的代码完全独立于Boolean.CompareTo 中的代码。它不会转换为整数来进行比较,它甚至不在乎您是否可以根据整数来考虑布尔值。它只是定义了在升序排序时 false 出现在 true 之前 - 任何地方都不涉及任何数字。
    【解决方案3】:

    排序与优先级无关——它与序数值有关。您正在对一个布尔值进行升序排列,在这种情况下,false 的序数值低于 true

    【讨论】:

      【解决方案4】:

      基本上,false 早于 true... 将它们视为 false=0,true=1。这与documentation for bool.CompareTo(bool) 一致。

      如果您想优先考虑“真”值,只需使用OrderByDescending

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-10
        • 2020-12-24
        • 1970-01-01
        • 2023-03-23
        • 2012-07-25
        • 2020-06-10
        相关资源
        最近更新 更多