Question

var Students = new Dictionary<string, int>();
Students.Add( "Bob" , 60);
Students.Add( "Jim" , 62);
Students.Add( "Jack", 75);
Students.Add( "John", 81);
Students.Add( "Matt", 60);
Students.Add( "Jill", 72);
Students.Add( "Eric", 83);
Students.Add( "Adam", 60);
Students.Add( "Gary", 75);

var MyVar  = Students.GroupBy(r=> r.Value)
                     .ToDictionary(t=> t.Key, t=> t.Select(x=> x.Key));

The Students object has Name and Weight key-value pairs.

In the ToDictionary method, t variable is of type IEnumerable<IGrouping<K, T>>. That is, IEnumerable<IGrouping<int, Students>>

Why are the Key values returned by t=>t.Key and t=> t.Select(**x=> x.Key**) different? They both use the same t variable. Key should be of type int.

The image was taken after the GroupBy method had been executed.(It is not the full image) One of the Key has the value of 60 and the other one has the values of Bob, Matt and Adam.

enter image description here

Was it helpful?

Solution

Because it's not a

IEnumerable<IGrouping<int, Student>>

It's a

IEnumerable<IGrouping<int, KeyValuePair<int, Student>>>

In t => t.Key you're referring to the grouping key, and in Select(x => x.Key) you're referring to the KeyValuePair.

You can hover over the variables in Visual Studio to see the types and the type parameters.

In more detail:

// return an IEnumerable<IGrouping<int, KeyValuePair<int, Student>>>
Students.GroupBy(r=> r.Value)
// iterate over each IGrouping<int, KeyValuePair<int, Student>>
    .ToDictionary(
        group => group.Key,
// iterate over each KeyValuePair<int, Student> in the group
// because IGrouping<TKey, TElement> inherits from IEnumerable<TElement>
// so it's a Select over an IEnumerable<KeyValuePair<int, Student>>
        group => group.Select(pair => pair.Key));

OTHER TIPS

It is creating a new dictionary with number as Key and all the student names from original dictionary related to particular key.

Here is how it works.

Why are the Key values returned by t=>t.Key

That is operating over the GroupBy, since GroupBy is applied on Value, which is int in the original dictionary. Thus the new dictionary would have the distinct keys based on original dictionary's values.

and t=> t.Select(x=> x.Key) different?

Now this Select is operating on each GroupBy item from original dictionary. Where Key is the student name. Thus getting all the student names based on the Key selected previously in GroupBy

This is what the result of Students.GroupBy(r => r.Value) looks like. It's a bit confusing, since both GroupBy as well as Dictionary use a Key.

    { (Key = 60, {(Key = "Bob", Value = 60), (Key = "Matt", Value = 60), ...}),
      (Key = 62, {(Key = "Jim", Value = 62)}),
      (Key = 72. ...),
      ...
    }

t is one row of this grouping.

The first selector t.Key yields 60.

The second selector t.Select(x => x.Key) operates on the list and yields {"Bob", "Matt", "Adam"}.

The Key of the IGrouping (t.Key) is the key that you grouped on in GroupBy. In this case this is the Value of the KeyValuePair.

The Key within the Select (x.Key) is getting the key of the KeyValuePair for each pair within the group.

It's somewhat less obvious here due to the inferred types, but you can hover over both x and t in visual studio to see that t is an IGrouping and x is a KeyValuePair. You could also improve the clarity of this query (quite a bit, in my mind) by using more meaningful variable names.

var MyVar = Students.GroupBy(pair => pair.Value)
                        .ToDictionary(group => group.Key,
                        group => group.Select(pair => pair.Key));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top