views:

139

answers:

3

I have the 2 collections:

IEnumerable<Element> allElements
List<ElementId> someElements, 

What is a concise way of doing the following together:

[1] Verifying that all elements in someElements exist in allElements, return quickly when condition fails.

and

[2] Obtain a list of Element objects that List<ElementId> someElements maps to.

Every Element object has an ElementId

Thank you.

A: 
  1. someElements.All(e => allElements.Contains(e));
  2. allElements.Where(e => someElements.Contains(e.ElementId));
Mark Cidade
+7  A: 

I would do this:

var map = allElements.ToDictionary(x => x.Id);    
if (!someElements.All(id => map.ContainsKey(id))
{
    // Return early
}
var list = someElements.Select(x => map[x])
                       .ToList();

Note that the first line will throw an exception if there are any duplicates in allElements.

Jon Skeet
this is awesome solution, this clearly shows that while using linq people still need to understand complexity and other fundamental algorithmic stuff. but for small lists it may be an overhead.
Andrey
In the case where there are duplicates, your DistinctBy method from MoreLinq would come in handy: http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/DistinctBy.cs
tvanfosson
+1  A: 

Not as efficient as the Skeet answer, but good enough for reasonable-sized collections:

IEnumerable<Element> allElements = new List<Element>
    { new Element { Id = 1 }, new Element { Id = 2 } };
List<int> someElements = new List<int> { 1, 2 };

var query =
    (from element in allElements
    join id in someElements on element.Id equals id
    select element)
    .ToList();

if (query.Count != someElements.Count)
{
    Console.WriteLine("Not all items found.");
}

foreach (var element in query)
{
    Console.WriteLine ("Found: " + element.Id);
}
TrueWill