开发者

OrderBy, ThenBy and IOrderedEnumerable<T>

开发者 https://www.devze.com 2023-03-02 13:38 出处:网络
string[] fruits = { \"grape\", \"passionfruit\", \"banana\", \"mango\", \"orange\", \"raspberry\", \"apple\", \"blueberry\" };
    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);

If we need more ordering than it is possible with a single call to OrderBy, then we should subsequently call ThenBy instead of OrderBy, since the sort performed by ThenBy is stable and thus preserves the开发者_JAVA百科 ordering of input elements with equal key values.

a) In the above example OrderBy returns IOrderedEnumerable<> sequence R and in turn ThenBy is called on this sequence. When OrderBy returns R, does R also store the key values (fruit.Length values ) which were used by OrderBy to sort the elements in R?

b) Where in R are key values stored?

Thank you


I think the answer to this question lies somewhere different than you are thinking;

OrderBy and ThenBy are what are known as "deferred operators". What you described as the behavior is correct on some level, but actually not...

OrderBy does return a reference of the type you suggest. But that object is not a collection in the traditional sense; It is a part of an expression tree. Subsequent calls to ThenBy further modify this expression tree.

Said expression tree might actually do the sorting in the reverse order to what you might assume. It might even detect that you tried to do the same sorting each time, and not do them both (you haven't done any such thing in your example code, but I'm just making a point).

In particular, doing a single OrderBy and ThenBy could actually be quickly and easily done by doing those sorts... in reverse. Keeping in mind what is said about OrderBy being non-determinate...

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

Assuming BubbleSort is a method which sorts by going down the list comparing each item to the next, and exchanging places when required (leaving equal cases alone), and repeats until the whole list no longer needs exchanging... this would end up with the same results as the LINQ methods you post... but note that it does the sort by names alpha first. When it sorts by length later, it would leave names of equivalent length in their alphabetical order, thereby appearing to OrderBy the length "first", then alphabetically.

OrderBy and ThenBy probably don't do a Bubble Sort (it's very inefficient on collections of any appreciable size at all), but to understand what they do, you need to understand they are building an expression tree that is executed when you enumerate the collection, and that expression tree is taking the total list of operations into account. It is not merely doing one sort, then doing the next... each as separate operations.


There are no "keys." OrderBy returns an enumerable of the same type as the original enumerable.


Your key values are generated from the elements in the list. Since you still have access to the elements in the sorted list, you can still get the key value:

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

Is that what you mean?? Maybe you are thinking about GroupBy, which would collect items with the same key value together?

0

精彩评论

暂无评论...
验证码 换一张
取 消