19

I have 2 lists of different objects (foo & bar) that share the same property lets call it id.

public List<foo> foo { get; set; }
public List<bar> bar { get; set; }

I want to remove all objects from foo that have an id that does not exist in bar

How can this be done in linq? I have been looking at Intersect, RemoveAll & Join but cannot find any example where the lists are of a different type.

ojhawkins
  • 3,200
  • 15
  • 50
  • 67

2 Answers2

30

Try this:

foo.RemoveAll(x=> !bar.Any(y=>y.Id==x.Id));

!bar.Any(y=>y.Id==x.Id) will get if item is in bar collection and if it's not it will remove it from foo collection.

Better solution using hashset O(n):

var idsNotToBeRemoved = new HashSet<int>(bar.Select(item => item.Id));                     
foo.RemoveAll(item => !idsNotToBeRemoved.Contains(item.Id));

source of second answer: https://stackoverflow.com/a/4037674/1714342

EDIT:

as @Carra said, first solution is good for small lists and second is more efficient for big lists.

Community
  • 1
  • 1
Kamil Budziewski
  • 22,699
  • 14
  • 85
  • 105
  • 2
    For small lists, the first will do. If you're using big lists (> 100 or so), you're better of using the second solution. – Carra Oct 04 '13 at 07:24
8
var foo = foo.Where(f => !bar.Any(b => b.Id == f.Id)).ToList();

Just keep in mind that this is a O(n²) solution, it won't work very well for big lists.

Carra
  • 17,808
  • 7
  • 62
  • 75
  • What would be a more effcient solution to this? @Carra – ojhawkins Oct 04 '13 at 07:08
  • @ojhawkins One solution would be to pre-collect the list of `id`s from `bar` into a hashset (O(n)) then compare each element in `foo` to that (O(n)) rather than walking the `bar` list for every element in `foo` – lc. Oct 04 '13 at 07:11
  • yes I did see Jon Skeets example here but could no apply it to my example http://stackoverflow.com/questions/853526/using-linq-to-remove-objects-within-a-listt – ojhawkins Oct 04 '13 at 07:12
  • `new HashSet(bar.Select(x => x.id))` ought to do, assuming you have no collisions – lc. Oct 04 '13 at 07:14
  • Using a hashset to save your ids should work, check wudziks example. – Carra Oct 04 '13 at 07:25