LINQ:从列表中选择对象不包含项的地方


77

我在这里用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根据另一个列表中的对象过滤掉我的对象列表。我希望这是有道理的。我想我只是失去了对包含部分......我不知道该怎么写。

Answers:


127

通常,您正在寻找“ Except”扩展名。

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

在此示例中,GenerateRegectStatuses()应该是您希望拒绝的状态列表(或更具体而言,根据您的示例List<int>为ID)


这真的很接近...诀窍是从动态状态创建拒绝列表。这将更像i => i.Status in(list <statuses>)的位置。我可以那样做吗?我猜基本上是另一条LINQ语句?
farina

1
绝对,要构建拒绝列表,您只需设计一种方法即可获取不需要的拒绝列表。例如:var rejectList = fullList.Where(i => rejectStatuses.Contains(i.Status)); 我将更新原始答案以反映此更改。
Thebigcheeze 2011年

2
我将如何在一行中做到这一点?我了解这可能无法实现。
JustJohn '16

78

将其转储到您不想要的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'2015-4-3

这个答案是比选择更好
Rarepuppers

干净简单!尼斯
Cata Hotea '18

@Rarepuppers-我花了几分钟的时间试图理解已接受的答案,然后看这里查看在我确定它是否可以正常工作之前已经输入的建议……
jleach

这应该是公认的答案。我一直在寻找了解它是如何工作的。万分感谢!
Xonshiz

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,编译器可能会发现它是模棱两可的。
贾斯汀·摩根

4

试试这个简单的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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.