zhulien
zhulien

Reputation: 557

Sorting a dictionary value which is a list of objects by given fields

I have a SortedDictionary whose value is a List of objects. I want to sort the value(the list) of each key by a given property of the object. In the current situation, I need to sort the list first by objects's lastname, then by firstname. I tried LINQ and it got nasty pretty fast without producing the result.

EDIT:

I have the following structure:

    public class Person
    {
        private string firstName;
        private string lastName;

        ...
    }

I need the dictionary sorted by the key. However, I need every List to be sorted first by Person's lastName, then by firstName.

var dict = new SortedDictionary<string, List<Person>>();

I didn't provide code for the sorting because i can't get it to work. That's why I seek help.

Upvotes: 0

Views: 3398

Answers (3)

Ben
Ben

Reputation: 15

I had a similar challenge and solved it by sorting the dictionary containing an object as Value on the fly in the foreach(..) statement.

Here is a sample of how I did it../ given the original scenario...

public class Person
  {
    private string firstName;
    private string lastName;  
    ...
  }

...
Dictionary<string, Person> dictPersons = new Dictionary<string, Person>();
// statements to populate the dictionary with keys and a Person objects.
....
foreach(var personEntry in dictPersons.ORderBy(p => p.Value.lastName).ThenBy(p => p.Value.firstName)
  {
  ...
  // When you use the firtName or lastName properties,just refer to it as:
  Console.WriteLine("LastName: {0}  FirstName: {1}", personEntry.Value.lastName, personEntry.Value.firstName);
  ...
}

Hope this helps some-one who needs it in future...

Upvotes: 0

Stefan Steinegger
Stefan Steinegger

Reputation: 64628

Generally I would create a new IEnumerable instead of trying to alter the existing collection. (This is the Linq way to do it):

IEnumerable<Tuple<string, List<Person>> dict = dict
 .Select(x => Tuple.Create(
    x => x.Key, 
    x => x.Value.OrderBy(x => x.LastName).ThenBy(x => x.FirstName)));

You can put it into a dictionary as well, but it is probably not needed. Either you want to have it sorted (where List is enought) or access by key (where you don't need it to be sorted, use ToDictionary in this case).

You probably don't even need a sorted dictionary as source, when you sort it at the end anyway (and add another OrderBy to the query).

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460098

You can use List.Sort, LINQ doesn't work in this case because you can't modify the dictionary(f.e. Add or using the Value property) during enumeration:

foreach(var kv in yourSortedDictionary)
{
    kv.Value.Sort((p1, p2) => {
        int diff = p1.LastName.CompareTo(p2.LastName);
        if(diff != 0) return diff;
        return p1.FirstName.CompareTo(p2.FirstName);
    });
}

This works even if it would better to add an already sorted list in the first place.

But as i've already mentioned in my comment, if the list cannot contain duplicates you could use a SortedSet<Person> instead of a List<Person>. .NET still lacks of a single value collection type that allows duplicates but is sorted.

Upvotes: 2

Related Questions