FadelMS
FadelMS

Reputation: 2037

Sort Dictionary based on values in a list of integers

I'm having a problem sorting a dictionary based on the sum of 1s in lists of integers inside the same Dictionary. So first I want to count the 1s in each list and then sort the dictionary based on the result. I've found some solutions in Stackoverflow but they don't answer my question.

Th dictionary looks like the following:

Dictionary<int, List<int>> myDic = new Dictionary<int, List<int>>();
List<int> myList = new List<int>();
myList = new List<int>();//Should appear third
myList.Add(0);
myList.Add(0);
myList.Add(1);
myDic.Add(0, myList);

myList = new List<int>();//Should appear second
myList.Add(1);
myList.Add(1);
myList.Add(0);
myDic.Add(1, myList);

myList = new List<int>();//Should appear first
myList.Add(1);
myList.Add(1);
myList.Add(1);
myDic.Add(2, myList);

I tried this code but it seems it doesn't do anything.

List<KeyValuePair<int, List<int>>> myList2 = myDic.ToList();
myList2.Sort((firstPair, nextPair) =>
 {
     return firstPair.Value.Where(i=>i==1).Sum().CompareTo(nextPair.Value.Where(x=>x==1).Sum());
});

Upvotes: 1

Views: 187

Answers (5)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236238

You are sorting list items in ascending order. I.e. items with more 1s will go to the end of list. You should use descending order. Just compare nextPair to firstPair (or change sign of comparison result):

myList2.Sort((firstPair, nextPair) =>
 {
     return nextPair.Value.Where(i => i==1).Sum().CompareTo(
                  firstPair.Value.Where(x => x==1).Sum());
});

This approach has one problem - sum of 1s in value will be calculated each time two items are compared. Better use Enumerable.OrderByDescending. It's more simple to use, and it will compute comparison values (i.e. keys) only once. Thus Dictionary is a enumerable of KeyValuePairs, you can use OrderByDescending directly with dictionary:

var result = myDic.OrderByDescending(kvp => kvp.Value.Where(i => i == 1).Sum());

Upvotes: 2

Servy
Servy

Reputation: 203842

Your code does do something. it creates a list of the items that used to be in the dictionary, sorted based on the number of 1 items contained in the list. The code that you have correctly creates this list and sorts it as your requirements say it should. (Note that using OrderByDescending would let you do the same thing more simply.)

It has no effect on the dictionary that you pulled the lists out of, of course. Dictionaries are unordered, so you can't "reorder" the items even if you wanted to. If it were some different type of ordered collection then it would be possible to change the order of it's items, but just creating a new structure and ordering that wouldn't do it; you'd need to use some sort of operation on the collection itself to change the order of the items.

Upvotes: -2

sglogowski
sglogowski

Reputation: 331

Maybe something simpler

myList2.OrderByDescending(x => x.Value.Sum());

Upvotes: 0

James Curran
James Curran

Reputation: 103515

class SummedKV
{
    public KeyValuePair Kvp {get; set;}
    public int Sum {get; set;}
}

var myList  =
         myDic.ToList()
              .Select(kvp=> new SummedKV {Kvp = kvp, Sum = kvp.Value.Sum() });
myList.Sort(skv=>skv.Sum);

Upvotes: 0

Keith
Keith

Reputation: 330

Your sort is backward, which is why you think it's not doing anything. Reverse the firstPair/nextPair values in your lambda and you'll get the result you expect.

Though, @Sergey Berezovskiy is correct, you could just use OrderBy, your example code could benefit from perhaps a different pattern overall.

Upvotes: 1

Related Questions