0

I currently use the following:

var result = list.Union(otherList).SelectMany(l => l.children).ToList()

foreach(var child in lotsOfChildren){
    something = result.Contains(child)
}

I only use result for querying if the list contains items, using result.Contains(x).

This look to be inefficient to me, as, presumably, Contains() has to enumerate the entire (static) list each time, to check if an item is contained.

I noticed ToDictionary() and ToLookup() extension methods, however both these require a key to be defined, which is unnecessary.

I guess what I'm really looking for is a ToHashSet() sort of thing - would I have to create this manually, as in .ToLookup(c => c.GetHashCode, c => c)? Or is there a built in method I'm missing? Or, alternatively, is this something the compiler will optimise, and I don't need to care about.

5
  • 1
    I would usually use ToDictionary for this. Isn't there a childID field you can use as a key?
    – rdans
    Commented Mar 13, 2015 at 12:15
  • @Ryan: Not specifically, but I presume GetHashCode() is much the same. Thanks
    – Chris
    Commented Mar 13, 2015 at 12:24
  • Unless your lists contain many duplicates, it's probably more efficient to do a Concat.SelectMany.Any/FirstOrDefault. Union and ToList require you to iterate the entire collection. The others are lazy (IIRC) and will only traverse as needed to find your target.
    – Telastyn
    Commented Mar 13, 2015 at 13:16
  • @Telastyn: Apologies, I've misunderstood - you might be on to something there. I was using the ToList for efficiency, but it doesn't seem to be required. list and otherList could be 99% equivalent, which is why I was using Union - which is lazy, isn't it?
    – Chris
    Commented Mar 13, 2015 at 13:42
  • @chris - eh, you are right. I took a peek in reflector and it is indeed lazy.
    – Telastyn
    Commented Mar 13, 2015 at 13:59

1 Answer 1

6

You can trivially define an extension method for ToHashSet if that's what you're looking for.

public static class Extensions
{
    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
    {
        return new HashSet<T>(source);
    }
}

You should now be able to use it in your original example:

var result = list.Union(otherList).SelectMany(l => l.children).ToHashSet()

foreach (var child in lotsOfChildren)
{
    something = result.Contains(child)
}
1
  • Thanks - this is of course nicer that my ToLookup() type thing. I was curious if there was a more natural way around this, but if this is the best there is, I'll go with it.
    – Chris
    Commented Mar 13, 2015 at 13:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.