OrderBy,ThenBy和IOrderedEnumerable <t> </t>

时间:2011-05-02 18:35:13

标签: 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返回 R 时, R 还会存储fruit.Length用于排序的关键值(OrderBy值)吗? R 中的元素?

b) R 中存储的键值是什么?

谢谢

3 个答案:

答案 0 :(得分:5)

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

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

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

所述表达式树实际上可能会按照 reverse 顺序进行排序。它甚至可能检测到你每次尝试进行相同的排序,而不是两者都做(你的示例代码中没有做过任何这样的事情,但我只是提出了一点意见)。

特别是,通过执行这些排序,实际上可以快速轻松地完成单个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可能不会进行冒泡排序(它在任何可观的大小的集合上都非常低效),但要了解它们的作用,您需要了解它们正在构建枚举集合时执行的表达式树,该表达式树将整个操作列表考虑在内。它不仅仅是做一种,而是做下一次......每次都是单独的操作。

答案 1 :(得分:2)

没有“钥匙”。 OrderBy返回与原始枚举类型相同的枚举。

答案 2 :(得分:1)

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

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

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