OrderBy, ThenBy 和 IOrderedEnumerable<T>


    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返回序列 R IOrderedEnumerable<>并依次在此序列上调用 ThenBy。当OrderBy返回 R 时,R 是否也存储 OrderBy 用来对 R 中的元素进行排序的键值(fruit.Length值(?

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 进行排序。当它稍后按长度排序时,它会按字母顺序保留同等长度的名称,从而看起来OrderBy长度"首先",然后按字母顺序排列。

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

没有"键"。 OrderBy返回与原始可枚举对象类型相同的枚举对象。

键值是从列表中的元素生成的。 由于您仍然可以访问排序列表中的元素,因此您仍然可以获取键值:

// enumerate the sorted list
foreach (string fruit in query) {
    int length = fruit.Length;  // grab the key value
    // do something with key value
}

这是你的意思吗?? 也许您正在考虑GroupBy,这会将具有相同键值的项目收集在一起?

相关内容

  • 没有找到相关文章