tezromania
tezromania

Reputation: 817

IComparer not working as expected

My program's function is to count the occurrences of unique words in a document, and then display them in sorted order. I first loop through all the words and enter them into a dictionary, and increment the value in the dictionary for how many times they have been encountered. I then convert the dictionary to a list and call the .Sort method with an IComparer as a parameter. Shown in this code here:

List<KeyValuePair<string,long>> wordList = wordCount.ToList();
IComparer<KeyValuePair<string,long>> comparison = new comparator();
wordList.Sort(comparison);

And the IComparer class I am using

public class comparator : IComparer<KeyValuePair<string, long>>
{
    public int Compare(KeyValuePair<string, long> x, KeyValuePair<string, long> y)
    {
        if (x.Value > y.Value)
            return 1;
        else
            return 0;
    }
}

However, when I am finished with the sorting, the list is not ordered by the value of the KeyValuePair like as I hoped it would be. What am I doing wrong here?

screen shot of poor sorting order

Upvotes: 1

Views: 975

Answers (2)

Felipe Oriani
Felipe Oriani

Reputation: 38638

Actually, you should return 1, 0 and -1 as a result fo the Compare method. But in your case, you could just use the CompareTo method from long type, for sample:

public class Comparator : IComparer<KeyValuePair<string, long>>
{
    public int Compare(KeyValuePair<string, long> x, KeyValuePair<string, long> y)
    {
        return x.Value.CompareTo(y.Value);
    }
}

As a good pratice, rename your class to Comparator and not comparator. Keep the clean code on!

Upvotes: 1

MarcinJuraszek
MarcinJuraszek

Reputation: 125660

You're missing the case when y.Value is greater than x.Value in your comparer implementation:

public class comparator : IComparer<KeyValuePair<string, long>>
{
    public int Compare(KeyValuePair<string, long> x, KeyValuePair<string, long> y)
    {
        if (x.Value > y.Value)
        {
            return 1;
        }
        else if (x.Value < y.Value)
        {
            return -1;
        }
        else
            return 0;
    }
}

or

public class comparator : IComparer<KeyValuePair<string, long>>
{
    public int Compare(KeyValuePair<string, long> x, KeyValuePair<string, long> y)
    {
        return x.Value.CompareTo(y.Value);
    }
}

You could also use LINQ OrderBy instead of Sort. It's easier to use because it takes a lambda expression, but it will create a new collection, instead of sorting the provided one.

var sorted = wordList.OrderByDescending(x => x.Value).ToList();

You could do all your processing in one query (assuming words is a collection of strings with all the words):

var sortedWithCount = words.GroupBy(x => x)
                           .OrderByDescending(g => g.Count)
                           .ToList(g => new { Word = g.Key, Count = g.Count });

Upvotes: 7

Related Questions