4

I'm trying to filter my first list of Foo's based on some values in a second list of Baa's.

For example.

Here's an example I put up on .NET Fiddle ...

var foos = new List<Foo>
{
    new Foo { Name = "Leia" },
    new Foo { Name = "Han Solo" },
    new Foo { Name = "Chewbacca" },
    new Foo { Name = "Luke" },
};

    var baas = new List<Baa>
{
    new Baa { Alias = "aaaaa" },
    new Baa { Alias = "bbbb" },
    new Baa { Alias = "Leia" },
    new Baa { Alias = "Luke" }
};

// Expected output:
// List<Foo> results = Foo { "Leia" } and Foo { "Luke" };

See how I'm asking for: Filter the first list (by Name) by the second lists Alias property.

and that will return a List of Foo with 2 results in it?

Any clues?

Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 2
    If your collections contain a lot of items, it might be wise to use `HashSet` instead of `List`. Checking if an item is contained in a `HashSet` is a O(1) operation, which can greatly improve the speed of computing the intersection. There is a dedicated method for this in the `HashSet` class, see: http://msdn.microsoft.com/en-us/library/vstudio/bb918911%28v=vs.90%29.aspx – Benlitz Apr 21 '14 at 13:12
  • *VERY* good point @Benlitz ! In my scenario, each list will be a few items only. But the answer(s) really help me for future dev where I might have to deal with list intersections. Would love to see some example code using the `Intersects` keyword if the two collections were `HashSet`'s. – Pure.Krome Apr 21 '14 at 13:15
  • @Pure.Krome You can't use `Intersect` because the lists are of two different types. – D Stanley Apr 21 '14 at 13:29
  • Ah! `HashSet` is against two of the same type. gotcha. – Pure.Krome Apr 21 '14 at 13:30
  • Yep I misread the question, however you can still do it if you use a `HashSet` and provides your own implementation of `IEqualityComparer` that can compare Foos and Baas. But that will lead to unsafe code so it should be done only if you have real performance issues and in the most internal/private way possible. I tested intersecting two collections of 10000 items, got 1400ms using lists and <1ms with hashset. Sample code here: http://pastebin.com/E6SJRDnr – Benlitz Apr 21 '14 at 14:00

2 Answers2

10

You can use Any on the list of baas:

foos.Where(f => baas.Any(b => b.Alias == f.Name));

Or use a join (cleaner in query syntax):

var query = 
    from f in foos
    join b in baas on f.Name equals b.Alias
    select f;

Here's the code in a full working .NET Fiddle.

joce
  • 9,624
  • 19
  • 56
  • 74
D Stanley
  • 149,601
  • 11
  • 178
  • 240
5

You could use Join:

var results = foos.Join(baas, f => f.Name, b => b.Alias, (f, b) => f);

Similar to this answer.

Community
  • 1
  • 1
Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194