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 的什么位置?
谢谢
我认为这个问题的答案与您想象的不同;
OrderBy
和ThenBy
就是所谓的"递延运算符"。您描述的行为在某种程度上是正确的,但实际上并非如此......
OrderBy
确实返回您建议的类型的引用。但该对象不是传统意义上的集合;它是表达式树的一部分。后续调用ThenBy
进一步修改此表达式树。
所述表达式树实际上可能以与您可能假设的相反的顺序进行排序。它甚至可能会检测到您每次都尝试执行相同的排序,而不是同时执行它们(您在示例代码中没有做任何这样的事情,但我只是提出一个观点(。
特别是,做一个OrderBy
和ThenBy
实际上可以通过做这些事情快速轻松地完成......反过来。记住关于OrderBy
是不确定的......
var names = //initialize list of names;
var namesByAlpha = BubbleSort(names=>names);
var namesByAlphaAndLength = BubbleSort(namesByAlpha=>namesByAlpha.Length);
假设BubbleSort
是一种方法,该方法通过向下比较列表将每个项目与下一个项目进行比较,并在需要时交换位置(单独保留相等的情况(,并重复直到整个列表不再需要交换......这最终会得到与您发布的 LINQ 方法相同的结果...但请注意,它首先按名称 alpha 进行排序。当它稍后按长度排序时,它会按字母顺序保留同等长度的名称,从而看起来OrderBy
长度"首先",然后按字母顺序排列。
OrderBy
和ThenBy
可能不会执行冒泡排序(对于任何可观大小的集合来说,它的效率非常低(,但要了解它们的作用,您需要了解它们正在构建一个表达式树,该表达式树在您枚举集合时执行,并且该表达式树考虑了操作的总列表。它不仅仅是做一种,然后做下一种......每个操作都是单独的操作。
没有"键"。 OrderBy
返回与原始可枚举对象类型相同的枚举对象。
键值是从列表中的元素生成的。 由于您仍然可以访问排序列表中的元素,因此您仍然可以获取键值:
// enumerate the sorted list
foreach (string fruit in query) {
int length = fruit.Length; // grab the key value
// do something with key value
}
这是你的意思吗?? 也许您正在考虑GroupBy
,这会将具有相同键值的项目收集在一起?