Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Let the SequenceEqual Work for the list

Tags:

c#

linq

I have a class named Country. It has the public members, 'CountryName' and 'States'.

I have declared a list of Countries.

Now I want to write a function which accepts a new 'Country' and decides if CountryList already has the 'Country'.

I tried writing a function like

bool CheckCountry(Country c)
{
    return CountryList.Exists(p => p.CountryName == c.Name
                                && p.States.SequenceEqual(c.States));
}

As I want to compare States using the CountryName property of the States, I want to modify my function so that SequenceEqual works based on the CountryName of the states?

like image 929
priyanka.sarkar Avatar asked Jun 16 '09 02:06

priyanka.sarkar


3 Answers

Break it down into many simple queries, and then put those queries back together.

Let's start by making a sequence of items that match by name:

var nameMatches = from item in itemList where item.Name == p.Name select item;

We need to compare those items against the sequence of names in p's subitems. What's that sequence? Write a query:

var pnames = from subitem in p.SubItems select subitem.Name;

Now you want to find all the elements from nameMatches where the sequence of names matches. How are you going to get the sequence of names? Well, we just saw how to do that with pnames, so do the same thing:

var matches = from item in nameMatches
              let subitemNames = 
                  (from subitem in item.SubItems select subitem.Name)
              where pnames.SequenceEqual(subitemNames)
              select item;

And now you want to know, are there any matches?

return matches.Any();

That should work just fine as is. But if you want to be really buff you can write the whole thing in one big query!

return (
    from item in itemList
    let pnames = 
        (from psubitem in p.SubItems select psubitem.Name)
    let subitemNames = 
        (from subitem in item.SubItems select subitem.Name)
    where item.Name == p.Name
    where pnames.SequenceEqual(subitemNames)
    select item).Any();

And you're done. Easy as pie! Just remember, break it down into small steps, solve each problem individually, and then put the solution together out of the small results.

like image 119
Eric Lippert Avatar answered Nov 10 '22 21:11

Eric Lippert


Have you looked at implementing IComparer on Item?

like image 25
jasonh Avatar answered Nov 10 '22 23:11

jasonh


If i understand you correctly you want a way to compare two items in which you first check the name of the two items then sequentially check each subitem's name. Here's what you want:

    public override bool Equals(object obj)
    {
        return this.Name == (obj as Item).Name;
    }
    public override int GetHashCode()
    {
        return this.Name.GetHashCode();
    }
    public bool Check(Item obj)
    {
        if (this.Name != obj.Name)
            return false;
        //if the lists arent of the same length then they 
        //obviously dont contain the same items, and besides 
        //there would be an exception on the next check
        if (this.SubItems.Count != obj.SubItems.Count)
            return false;
        for (int i = 0; i < this.SubItems.Count; i++)
            if (this.SubItems[i] != obj.SubItems[i])
                return false;
        return true;
    }
like image 1
RCIX Avatar answered Nov 10 '22 23:11

RCIX