LINQ:选择不包含列表项的对象

86

我在这里遇到了LINQ语法的困难...想在这里求助一下。我无法在其他地方找到我要寻找的内容。

好的,假设我有这个:

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();

长话短说,我想使用LINQ根据另一个列表中的对象过滤出我的对象列表。我希望这有意义。我想我只是在Contains部分迷失了方向......我不知道该如何编写代码。

4个回答

138

一般来说,你需要寻找“Except”扩展。

var rejectStatus = GenerateRejectStatuses();
var fullList = GenerateFullList();
var rejectList = fullList.Where(i => rejectStatus.Contains(i.Status));
var filteredList = fullList.Except(rejectList);
在这个例子中,GenerateRegectStatuses() 应该是您希望拒绝的状态列表(或更具体地说,基于您的示例,一个 ID 的 List<int>)。

这真的很接近了...诀窍在于从动态状态创建rejectList。它更像是 i => i.Status in(list<statuses>)。我能做类似的事情吗?基本上另一个LINQ语句,我猜? - farina
1
绝对的,要建立rejectList,你只需要想出一种获取不想要拒绝列表的方法。例如:var rejectList = fullList.Where(i => rejectStatuses.Contains(i.Status));我会更新我的原始答案以反映这个变化。 - Thebigcheeze
2
我该如何用一行代码实现这个?我知道可能不太可能。 - JustJohn

93

将这个内容转储至一个更具体的集合,仅包含您不想要的ID。

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

那么尝试这个:

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

或者这样:

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

好的,我更喜欢这个答案。+1 - JoshYates1980
这个答案比被选中的更好。 - Rarepuppers
简洁明了!很好。 - Cata Hotea
1
@Rarepuppers - 我花了几分钟时间试图理解被接受的答案,然后在这里查看建议,确认我已经打过的东西是否是正确的... - jleach
这应该是被接受的答案。我一直在努力理解它的工作原理。非常感谢! - Xonshiz

7

尝试使用这个简单的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();

5

我没有尝试过这个,所以我不能保证任何东西,然而

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
据我所知,b.ID不能编译。Contains 方法似乎丢失了 b 的上下文。 - farina
2
你使用了两个名为 b 的变量,编译器可能会发现它不明确。 - Justin Morgan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接