+ 4

[C#] Help with understanding the Comparison delegate with List.Sort() method

Hey everyone, I have a question. I am learning C#, and I love it so far :) I am struggling a bit in understanding the usage of the "Comparison" delegate when invoked via the List.Sort() method. So basically, I am trying to sort a list of strings in a list, and one solution that came across is using a lambda function with the "sort()" method as follows: List<string> wordDictionnary = new List<string>(); wordDictionnary.Add("John"); wordDictionnary.Add("Elena"); wordDictionnary.Add("Genevieve"); wordDictionnary.Sort((x, y) => x.Length - y.Length); Although I do understand lambdas functions, and the fact that the first overload of the method is the invocation of the "Comparison<T>" delegate, I don't understand how this works. My understanding is that x and y are simply two instances of the list (?) passed as parameters to the delegate function. But how is the function able to compare the two lists? How does it iterate over each word in the list to determine their length? What's even more confusing for me is that the official documentation shows the prototype of that comparison delegate: > https://docs.microsoft.com/en-us/dotnet/api/system.comparison-1?view=netframework-4.8#examples "dinosaurs.Sort(CompareDinosByLength);" In this example, the method is invoked without any param., although it requires two params. How does that work? How is that function able to extract "x" and "y"? Thanks for your guidance fellow sololearners :)

27th Jan 2020, 5:15 AM
Kronickoo
11 Antworten
+ 2
The lambda is not subtracting <x> by <y>, it is subtracting the length of string <x> by the length of string <y>. It was done in order to sort the List items by its items' length (shortest to longest). For example, the List::Sort method extracts two adjacent items, and assign them as: x = "C#" // length 2 y = "Python" // length 6 Then the List::Sort calls the lambda, passing <x> and <y>. The lambda subtracts length of <x> by length of <y> (2 - 6) which results in negative number (-4). This result is then returned to List::Sort method which understood that a negative number (-4) means that <x> should be moved before <y> in case it was not already. This is done by swapping the items (<x> and <y>) position within the List.
27th Jan 2020, 7:03 PM
Ipang
+ 4
Kronickoo In this line, dinosaurs.Sort(CompareDinosByLength); The `CompareDinosByLength` is not being invoked, it is rather being passed as an argument for the `List::Sort`, to inform the List::Sort method that it should rely on the value returned by `CompareDinosByLength` for sorting items. The List::Sort method is the one responsible for extracting two values (string in this case) from the list. These two values are then passed to the "Comparison" delegate, which checks the two given arguments, and may return either one of these: 0. If the first and second argument are considered equivalent (no reordering necessary). 1. If the first argument should be moved after the second argument. -1. If the first argument should be moved before the second argument List::Sort method calls `CompareDinosByLength` passing two adjacent items from the list, again and again, until all the items are sorted. Hth, cmiiw
27th Jan 2020, 5:06 PM
Ipang
+ 2
Thanks lpang for taking the time to reply, I understand a bit better now. Regarding the lambda function, why is Y subtracted from X? "wordDictionnary.Sort((x, y) => x.Length - y.Length);" If the List::Sort(method) is able in itself to extract two values from a list, wouldn't something like this been simpler: wordDictionnary.Sort((x => x.Length); Why comparing two instances of that same list?
27th Jan 2020, 6:17 PM
Kronickoo
+ 2
Thanks lpang. Could you guide me on how to print the value of x and y in the lamba expression? I tried, but I'm not doing it right. aList.Sort((x, y) => { x.Length - y.Length; Console.WriteLine(x, y); } ); } Throws the following exception: test.cs(17,23): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement. Is there a way to have the values being parsed by the delegate and output the content as well?
27th Jan 2020, 9:16 PM
Kronickoo
+ 2
Excellent, it worked :) I get it now. To sum up. The iteration is performed by the "List::Sort()" method. One of its overload is the usage of a method (delegate) that returns the biggest of two values (x.Length) and (y.Length). The List::Sort() method defines an algorithm that iterates over the values in the list to determine the sorting. I created a text file in which I put some keywords to track the sorting. The first value is the index (starts at 1 for clarity), then the word, followed by its length: Number of words: 8 x = 2:Holder(6) y = 1:Cups(4). Result: 2 x = 3:Doors(5) y = 2:Holder(6). Result: -1 x = 3:Doors(5) y = 1:Cups(4). Result: 1 x = 4:at(2) y = 2:Holder(6). Result: -4 x = 4:at(2) y = 3:Doors(5). Result: -3 x = 4:at(2) y = 1:Cups(4). Result: -2 x = 5:Elephant(8) y = 2:Holder(6). Result: 2 x = 6:Jump(4) y = 5:Elephant(8). Result: -4 x = 6:Jump(4) y = 2:Holder(6). Result: -2 x = 6:Jump(4) y = 3:Doors(5). Result: -1 x = 6:Jump(4) y = 1:Cups(4). Result: 0 x = 7:Space(5) y = 5:Elephant(8). Result: -3 x = 7:Space(5) y = 2:Holder(6). Result: -1 x = 7:Space(5) y = 3:Doors(5). Result: 0 x = 8:vehicle(7) y = 5:Elephant(8). Result: -1 x = 8:vehicle(7) y = 2:Holder(6). Result: 1 Words sorted: 4:at(2) 1:Cups(4) 6:Jump(4) 3:Doors(5) 7:Space(5) 2:Holder(6) 8:vehicle(7) 5:Elephant(8) Thanks again lpang for taking the time to explain, this was super helpful :)
28th Jan 2020, 12:59 AM
Kronickoo
+ 1
thanks lpang. I edited the post.
27th Jan 2020, 4:13 PM
Kronickoo
+ 1
To understand what <x> and <y> actually are, you can print them within the lambda or the comparison delegate. You will see how the List::Sort works better. The lambda and comparison delegate are working with items of the List, not the List instance itself.
27th Jan 2020, 7:13 PM
Ipang
+ 1
Try to print them like this And don't forget to return the length subtraction result, it is needed by List::Sort to understand how the items are supposed to be ordered 👍 Console.WriteLine("x = {0} y = {1}", x, y);
28th Jan 2020, 12:02 AM
Ipang
0
I feel a bit confused reading your last paragraph; "In this example, the list is passed as a first parameter to the function" Which example? yours, or the one in the link? also which function? "Whereas the function admits two parameters." Which function are you referring to by this sentence? Please confirm ... (Edited)
27th Jan 2020, 8:13 AM
Ipang
0
I'm repeating after general Hannibal Smith; "I love it, when a plan comes together" 😁 Good job! 👍
28th Jan 2020, 1:13 AM
Ipang
0
Thank you 👉
28th Jan 2020, 5:31 AM
Kronickoo