90

I'm struggling with LINQ syntax here...thought I'd toss it out here. I cant find exactly what I'm looking for anywhere else.

OK, say I've got this:

public class Bar
{
   public int BarId { get; set; }
}

public class Foo
{
   public List<Bar> BarList { get; set; }
}

List<Foo> fooBunch = GetABunchOfFoos(); //let's just assume I'm getting more than one
List<Foo> fooSelect = new List<Foo>;
List<Bar> filterBars = GetAFewBars(); //assume I'm getting like 2 or 3

fooSelect = (from f in fooBunch
             where !(from b in f.BarList select b.BarId).Contains(ITEM FROM filterBars.BarId)
             select f).ToList();

So, long story short I want to use LINQ to filter out my list of objects based on objects from another list. I hope this makes sense. I think I'm just lost on the Contains portion...I don't know how to write that.

4 Answers 4

141

In general, you're looking for the "Except" extension.

var rejectStatus = GenerateRejectStatuses();
var fullList = GenerateFullList();
var rejectList = fullList.Where(i => rejectStatus.Contains(i.Status));
var filteredList = fullList.Except(rejectList);

In this example, GenerateRegectStatuses() should be the list of statuses you wish to reject (or in more concrete terms based on your example, a List<int> of IDs)

Sign up to request clarification or add additional context in comments.

3 Comments

This is really close...the trick would be to create the rejectList from dynamic statuses. It would be more like where i => i.Status in(list<statuses>). Can I do something like that? Basically another LINQ statement I guess?
Absolutely, to build the rejectList, you'd just have to devise a way to get a list of rejects you don't want. For example: var rejectList = fullList.Where(i => rejectStatuses.Contains(i.Status)); I'll update my original answer to reflect this change.
How would I do this in just one line? I understand it might not be possible.
96

dump this into a more specific collection of just the ids you don't want

var notTheseBarIds = filterBars.Select(fb => fb.BarId);

then try this:

fooSelect = (from f in fooBunch
             where !notTheseBarIds.Contains(f.BarId)
             select f).ToList();

or this:

fooSelect = fooBunch.Where(f => !notTheseBarIds.Contains(f.BarId)).ToList();

5 Comments

Nice. i like this answer better. +1
This answer is better than the selected
Clean and simple ! Nice
@Rarepuppers - I spend a few minutes trying to understand the accepted answer, then looked here to see suggested what I already typed before I knew for sure if it worked that way...
This should be the accepted answer. I've been looking to UNDERSTAND how it works. Thanks a ton!
7

Try this simple LINQ:

//For a file list/array
var files = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories);

//simply use Where ! x.Contains
var notContain = files.Where(x => ! x.Contains(@"\$RECYCLE.BIN\")).ToList();

//Or use Except()
var containing = files.Where(x => x.Contains(@"\$RECYCLE.BIN\")).ToList();
    notContain = files.Except(containing).ToList();

Comments

5

I have not tried this, so I am not guarantueeing anything, however

foreach Bar f in filterBars
{
     search(f)
}
Foo search(Bar b)
{
    fooSelect = (from f in fooBunch
                 where !(from b in f.BarList select b.BarId).Contains(b.ID)
                 select f).ToList();

    return fooSelect;
}

2 Comments

From what I can tell, b.ID doesn't compile. The Contains method seems to loose context of b.
You're using two variables named b, and the compiler probably finds it ambiguous.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.