2

Suppose I have a dictionary<int, string> like this

dict1 = {{[4,bcefgh]},{[5,abcefgh]},{[6,efgh]},{[7,bcefgh]},{[10,cefghi]}}

I want to sort pairs in this dictionary according to length of string values, without using extra loops. That is, results should be:

dict1 = {{[6,efgh]},{[4,bcefgh]},{[7,bcefgh]},{[10,cefghi]},{[5,abcefgh]}}

My initial answer was to create a separate dictionary that had the same keys and length of every corresponding string and a third dictionary that loops over pair as follows:

foreach (KeyValuePair<int,string> pair  in dict1)
{
    temp_dict.Add(pair.Key, pair.Value.Count());
}

var items = from pair in temp_dict
        orderby pair.Value ascending
            select pair;

foreach (KeyValuePair<int, int> pair in items)
{
    result_dict.Add(pair.Key, dict1[pair.Key]);
}

But this result is now practical with large set of data.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rational Rose
  • 73
  • 1
  • 10

3 Answers3

5

You can't count on Dictionary being sorted. Instead you can use SortedDictionary<string, string> and pass its constructor a custom IComparer<T>.

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
brz
  • 5,926
  • 1
  • 18
  • 18
4

If you can live with an IOrderedEnumerable of KeyValuePairs, this will work:

var dict1 = new Dictionary<int, string>
{
    {4, "bcefgh"},
    {5, "abcefgh"},
    {6, "efgh"},
    {7, "bcefgh"},
    {10, "cefghi"}
};

IOrderedEnumerable<KeyValuePair<int, string>> sortedDict =
    dict1.OrderBy(i => i.Value.Length).ThenBy(i => i.Key);


foreach (var keyValuePair in sortedDict)
{
    Console.WriteLine(keyValuePair.Key + ": " + keyValuePair.Value);
}

// Output:
// 6: efgh
// 4: bcefgh
// 7: bcefgh
// 10: cefghi
// 5: abcefgh
Rufus L
  • 36,127
  • 5
  • 30
  • 43
0

Here is what I use. A sorted set of key value pairs. Ordered by value length.

public class ValueSortedKeyValuePairSet : SortedSet<KeyValuePair <int, string>> 
    {

        private class StringLengthComparerDecending : IComparer<KeyValuePair <int, string>>
        {
            public int Compare(KeyValuePair <int, string> x, KeyValuePair <int, string> y)
            {
                var lengthComparison = x.Value.Length.CompareTo(y.Value.Length);
                return lengthComparison == 0 ? string.Compare(x.Value, y.Value, StringComparison.Ordinal) : lengthComparison;
            }
        }

        public ValueSortedKeyValuePairSet() : base(new StringLengthComparerDecending()) {}

        public ValueSortedKeyValuePairSet(IEnumerable<KeyValuePair <int, string>> e) : base(e, new StringLengthComparerDecending()) {}      
    }
}

Demo: https://dotnetfiddle.net/pklISX

herostwist
  • 3,778
  • 1
  • 26
  • 34