Rational Rose
Rational Rose

Reputation: 83

Sorting dictionary according to length of string values in C#

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.

Upvotes: 2

Views: 2110

Answers (3)

herostwist
herostwist

Reputation: 3968

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

Upvotes: 0

Rufus L
Rufus L

Reputation: 37060

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

Upvotes: 4

brz
brz

Reputation: 6016

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

Upvotes: 4

Related Questions