linq - OrderBy、ThenBy 和 IOrderedEnumerable<T>

标签 linq

    string[] fruits = { "grape", "passionfruit", "banana", "mango", 
                          "orange", "raspberry", "apple", "blueberry" };

    // Sort the strings first by their length and then 
    //alphabetically by passing the identity selector function.
    IEnumerable<string> query =
        fruits.OrderBy(fruit => fruit.Length).ThenBy(fruit => fruit);

如果我们需要比一次调用 OrderBy 可能的更多订购,那么我们应该随后调用 ThenBy而不是 OrderBy,因为排序由 ThenBy是稳定的,因此保留了具有相同键值的输入元素的顺序。

a) 在上面的例子中 OrderBy返回 IOrderedEnumerable<>序列 R 依次为 ThenBy在这个序列上被调用。当OrderBy返回 RR 是否还存储 fruit.Length 使用的键值(OrderBy 值)对 R 中的元素进行排序?

b) R 中的键值存储在哪里?

谢谢

最佳答案

我认为这个问题的答案与你想的不同;

OrderByThenBy 是所谓的“延迟运算符”。你所描述的行为在某种程度上是正确的,但实际上不是......

OrderBy 确实返回您建议的类型的引用。但是那个对象不是传统意义上的集合;它是表达式树的一部分。对 ThenBy 的后续调用会进一步修改此表达式树。

所述表达式树实际上可能按照您可能假设的反向顺序进行排序。它甚至可能检测到您每次都尝试进行相同的排序,而不是两者都进行(您在示例代码中没有做过任何此类事情,但我只是在说明一点)。

特别是,执行单个 OrderByThenBy 实际上可以通过反向执行这些排序来快速轻松地完成。请记住关于 OrderBy 不确定的说法...

var names = //initialize list of names;
var namesByAlpha = BubbleSort(names=>names);
var namesByAlphaAndLength = BubbleSort(namesByAlpha=>namesByAlpha.Length);

假设 BubbleSort 是一种方法,该方法通过将列表中的每个项目与下一个项目进行比较,并在需要时交换位置(不考虑相同的情况),并重复直到整个列表不再需要交换...这最终会得到与您发布的 LINQ 方法相同的结果...但请注意,它按名称 alpha first 进行排序。当它稍后按长度排序时,它会按照字母顺序保留相同长度的名称,因此 OrderBy 显示长度“首先”,然后按字母顺序。

OrderByThenBy 可能不会进行冒泡排序(对于任何可观大小的集合来说,它的效率都非常低),但要了解它们的作用,您需要了解他们正在构建一个表达式树,该树在您枚举集合时执行,并且该表达式树正在考虑整个操作列表。它不仅仅是做一个排序,然后做下一个......每个作为单独的操作。

关于linq - OrderBy、ThenBy 和 IOrderedEnumerable<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5860949/

相关文章:

c# - linq select 和 group by

c# - Entity Framework - 带有基于 NULLABLE 参数的 WHERE 子句的 LINQ 语句

c# - 帮助合并 XML 数据

linq - 如何使用 LINQ to SQL 预先加载同级数据?

c# - LINQ LEFT JOIN 不适用于 NULL 值

c# - 具有多个 from 子句的 Lambda LINQ 查询

c# - 使用 entityframework 重用 Linq to SQL 代码

c# - 如何在 LINQ 中对范围进行分组

linq - 如何创建一个必须满足两个值的谓词,其中一个是值列表?

c# - Entity Framework 中的任何 Vs 计数