Question

Im writing my own LINQ reference but Im getting troubles with some of the more complicated operators implementations.

There is a Join implementation that takes a IEqualityComparer Im getting just crazy.

Im trying to understand it first before I write (obviously)

Image this two lists:

List<string> initials = new List<string> {"A", "B", "C", "D", "E"};

List<string> words = new List<string> {"Ant", "Crawl", "Pig", "Boat", "Elephant", "Arc"};

Nothing weird here. I want to join both lists by the Initial, something like:

Initial=A Word=Ant
Initial=A Word=Arc
Initial=B Word=Boat
...

I need a comparator, I wrote this:

public class InitialComparator : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.StartsWith(y);
    }

    public int GetHashCode(string obj)
    {
        return obj[0].GetHashCode();
    }
}

The Join itself:

var blah = initials.Join(words,
                                  initial => initial,
                                  word => word,
                                  (initial, word) =>
                                  new {Initial = initial, Word = word},
                                  new InitialComparator());

It's the first time Im using HashCodes, after a good session of debugging I see that every word go to the comparator and look at its HashCode, if another word has the same HashCode it calls equals.

Since I want to compare just the initial I though that I just need the first letter Hash (Am I wrong?)

The thing is that this is not working correctly. Its says that "Ant" and "Arc" are equals, Ok, its comparing every word in the same list or not, But it adds only the last word it finds, in this case Arc, ignoring Ant and Ant is equals to "A" too...

If I put "Ant" and "Ant" it add both.

In short, What is the way of doing something like that? I know that Im doing something wrong.

Thank you.

Was it helpful?

Solution

As Crispy mentioned try x[0] == y[0] instead of x.StartsWith(y); That worked for me.

OTHER TIPS

You don't actually need your own equality comparer, just join on the individual letter like so:

var mine = from i in initials
     join w in words on i[0] equals w[0]
     select new {
          Initial = i,
          Words = w
     };

I'm not sure why you're seeing this behavior, but I think using "SelectMany" would be a more straightforward approach and (more importantly) has the behavior you want:

var blah =
    from word in words
    from initial in initials
    where (word.StartsWith(initial))
    select new { Initial = initial, Word = word };

I prefer to use the comprehension syntax where possible. "SelectMany" is invoked when there are multiple "from" clauses in a comprehension query.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top