views:

2373

answers:

5

I have a Dictionary<string, double> and I want to convert it to a SortedDictionary<double, string>. How do I do this using LINQ extension methods in C# 3.0?

EDIT: Generic angle brackets not in original question when Marc and Jared answered.

+12  A: 

edit this answer was before edit; for an answer to the updated problem, see this reply.

Why use LINQ? There is a constructor for this:

new SortedDictionary<int, string>(existing);

You could add a ToSortedDictionary - but I wouldn't bother...

Marc Gravell
Beat me by 20 seconds
JaredPar
Just realized that I didn't back-quote the angle brackets in my original question.
Guy
+4  A: 

No LINQ is needed. SortedDictionary has a constructor to do the conversion.

public SortedDictionary<TKey,TValue> Convert<TKey,TValue>(Dictionary<TKey,TValue> map) {
  return new SortedDictionary<TKey,TValue>(map);
}
JaredPar
+1  A: 

You don't need LINQ, just some nifty extension methods:

public static IDictionary<TKey, TValue> Sort<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
{
    if(dictionary == null)
    {
        throw new ArgumentNullException("dictionary");
    }

    return new SortedDictionary<TKey, TValue>(dictionary);
}

public static IDictionary<TKey, TValue> Sort<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
{
    if(dictionary == null)
    {
        throw new ArgumentNullException("dictionary");
    }

    if(comparer == null)
    {
        throw new ArgumentNullException("comparer");
    }

    return new SortedDictionary<TKey, TValue>(dictionary, comparer);
}

Example usage:

var dictionary = new Dictionary<int, string>
{
    { 1, "one" },
    { 2, "two" },
    { 0, "zero" }
};

foreach(var pair in dictionary.Sort())
{
    Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}

// 0: zero
// 1: one
// 2: two
Bryan Watts
+3  A: 

It seems as though you are asking for an elegant way to take a Dictionary<TKey,TValue> and turn that into a SortedDictionary<TValue,TKey> (note that the value of the Dictionary is now the key of the SortedDictionary). I don't see any answer addressing that so here it goes.

You could create an extension method that looks like this:

static class Extensions
{
    public static Dictionary<TValue, TKey> 
         AsInverted<TKey, TValue>(this Dictionary<TKey, TValue> source)
    {
     var inverted = new Dictionary<TValue, TKey>();

     foreach (KeyValuePair<TKey, TValue> key in source)
      inverted.Add(key.Value, key.Key);

     return inverted;
    }
}

And your application code would look like this:

using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
     var dict = new Dictionary<String, Double>();
     dict.Add("four", 4);
     dict.Add("three", 3);
     dict.Add("two", 2);
     dict.Add("five", 5);
     dict.Add("one", 1);

     var sortedDict = new SortedDictionary<Double, String>(dict.AsInverted());
    }
}
Andrew Hare
A: 

Inversion using ToDictionary:

public static IDictionary<TValue, TKey> Invert<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
{
    if(dictionary == null)
    {
        throw new ArgumentNullException("dictionary");
    }

    return dictionary.ToDictionary(pair => pair.Value, pair => pair.Key);
}

Example usage:

var dictionary = new Dictionary<string, int>
{
    { "zero", 0 },
    { "one", 1 },
    { "two", 2 }
};

foreach(var pair in dictionary.Invert())
{
    Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}

// 0: zero
// 1: one
// 2: two

Example of inverting and sorting (see my other answer for the definition of Sort):

var dictionary = new Dictionary<string, int>
{
    { "one", 1 },
    { "two", 2 },
    { "zero", 0 }
};

foreach(var pair in dictionary.Invert().Sort())
{
    Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}

// 0: zero
// 1: one
// 2: two
Bryan Watts