tags:

views:

880

answers:

2

I have two IEnumerable's. One gets filled with the fallback ellements. This one will always contain the most elements. The other one will get filled depending on some parameters and will possibly contain less elements. If an element doesn't exist in the second one, I need to fill it with the equivalent one of the first one.

This code does the job, but feels inefficient to me and requires me to cast the IEnumerables to ILists or to use a temporary list Person implements IEquatable

IEnumerable<Person> fallBack = Repository.GetPersons();
IList<Person> translated = Repository.GetPersons(language).ToList();

foreach(Person person in fallBack){
    if(!translated.Any(p=>p.equals(person)))
        translated.add(person);  
}

Any suggestions?

+13  A: 
translated.Union(fallback)

or (if Person doesn't implement IEquatable<Person> by ID)

translated.Union(fallback, PersonComparer.Instance)

where PersonComparer is:

public class PersonComparer : IEqualityComparer<Person>
{
    public static readonly Instance = new PersonComparer();

    // We don't need any more instances
    private PersonComparer() {}

    public int GetHashCode(Person p)
    {
        return p.id;
    }

    public bool Equals(Person p1, Person p2)
    {
        if (Object.ReferenceEquals(p1, p2))
        {
            return true;
        }
        if (Object.ReferenceEquals(p1, null) ||
            Object.ReferenceEquals(p2, null))
        {
            return false;
        }
        return p1.id == p2.id;
    }
}
Jon Skeet
Brilliant - As they say, you learn something new everyday!
Gavin Miller
Well, it's not quite ready yet...
Jon Skeet
That will only work though if the Person class properly implements Equality. Judging by the OP I'm guesssing they don't.
JaredPar
HAHA! Jon, couldn't you package it in more mumbo jumbo? I feel utterly stupid again :P
borisCallens
Actually they do. The OP also contains no real code. Partly because it simplifies my question and partly because my boss is terified of putting code in public areas :s
borisCallens
@Jared: I was getting there :)
Jon Skeet
Actually, I fear it seems it's not the solution I was aiming for.This will give me the collection with ALL elements from both in it and it will never hit my Equals(Person other) method.Am I doing something wrong or did I miscommunicate my question?
borisCallens
+1  A: 

Try this.

public static IEnumerable<Person> SmartCombine(IEnumerable<Person> fallback, IEnumerable<Person> translated) {
  return translated.Concat(fallback.Where(p => !translated.Any(x => x.id.equals(p.id)));
}
JaredPar