tags:

views:

284

answers:

4

edit: Thanks Jason, the fact that it was a dictionary isn't that important. I just wanted the runtime to have a low runtime. Is that LINQ method fast? Also, I know this is off topic but what does the n => n mean?

I have a list of numbers and I want to make another list with the numbers that appear most at the beginning and the least at the end.

So what I did was when through the list and checked if the number x was in the dictionary. If it wasn't then I made the key x and the value one. If it was then I changed the value to be the value plus one.

Now I want to order the dictionary so that I can make a list with the ones that appear the most at the beginning and the least at the end.

How can I do that in C#? ps. runtime is very important.

A: 
    List<KeyValuePair<type, type>> listEquivalent = 
new List<KeyValuePair<type, type>>(dictionary);    

    listEquivalent.Sort((first,second) =>
            {
                return first.Value.CompareTo(second.Value);
            });

Something like that maybe?

edit: Thanks Jason for the notice on my omission

Aggelos Mpimpoudis
There is no `Sort` method on `Dictionary`.
Jason
Grrrr.... I missed the part in which we instantiate a List by the dictionary object. I am really sorry. However LINQ seemed better from above! Thank you Jason for the note!List<KeyValuePair<type, type>> myList = newList<KeyValuePair<type, type>>(dictionary);
Aggelos Mpimpoudis
+9  A: 

So it sounds like you have a Dictionary<int, int> where the key represents some integer that you have in a list and corresponding value represents the count of the number of times that integer appeared. You are saying that you want to order the keys by counts sorted in descending order by frequency. Then you can say

// dict is Dictionary<int, int>
var ordered = dict.Keys.OrderByDescending(k => dict[k]).ToList();

Now, it sounds like you started with a List<int> which are the values that you want to count and order by count. You can do this very quickly in LINQ like so:

// list is IEnumerable<int> (e.g., List<int>)
var ordered = list.GroupBy(n => n)
                  .OrderByDescending(g => g.Count())
                  .Select(g => g.Key)
                  .ToList();

Or in query syntax

var ordered = (from n in list
               group n by n into g
               orderby g.Count() descending
               select g.Key).ToList();

Now, if you need to have the intermediate dictionary you can say

var dict = list.GroupBy(n => n)
               .ToDictionary(g => g.Key, g => g.Count());
var ordered = dict.Keys.OrderByDescending(k => dict[k]).ToList();
Jason
The latter is not quite the same. It creates a list of anonymous objects rather than a Dictionary. It may be sufficient for the purpose, but if the Dictionary is necessary rather than merely convenient, I'd use ToDictionary instead.
tvanfosson
thank you, that was very helpful.
Daniel
I ran it and I got the exception System.StackOverflowException what is wrong?
Daniel
You ran what with what input and got a `StackOverflowException`?
Jason
Never mind, I fixed it.
Daniel
A: 

Use the GroupBy extension on IEnumerable() to group the numbers and extract the count of each. This creates the dictionary from the list and orders it in one statement.

var ordered = list.GroupBy( l => l )
                  .OrderByDescending( g => g.Count() )
                  .ToDictionary( g => g.Key, g.Count() );
tvanfosson
A: 

You may also consider using SortedDictionary.

It sorts the items on the basis of key, while insertion. more..

Amby
He wants the keys of the dictionary sorted on their corresponding values which is quite different than what a `SortedDictionary` would provide.
Jason