Linq - 检查所有但只有至少有一个

时间:2016-09-06 09:00:56

标签: c# linq linq-to-sql

我在Linq编写一个查询,需要检查列表中的一个或多个项是否传递谓词A()传递谓词{ {1}}。它需要是单个查询才能启用Linq to SQL。因此,对于以下列表,结果应如下B()通过谓词aA()传递谓词b

B()

我尝试了以下方法,但每种方法都有某些失败的情况:

1. [ a, a ] => true
2. [ a ]    => true
3. [ a, b ] => false
4. [ b, b ] => false
5. [ b ]    => false
6. [ ]      => false

我觉得我需要的东西是等同于all的东西,但是对于空列表返回false。例如,这将在所有情况下通过:

// Fails in case 6
MyList.All(x => A(x) && !B(x));

// Fails in case 3
MyList.Where(x => !B(x)).Count(x => A(x)) > 0;

// This works, but it's not a single query anymore
MyList.All(x => A(x) && !B(x)) && Mylist.Count() > 0;

我怎样才能做到这一点?

5 个答案:

答案 0 :(得分:2)

你可以这样做:

var result = MyList
    .Select(x => B(x) ? -1 : (A(x) ? 1 : 0))
    .Aggregate(0, (p, v) => v == -1 || p == -1 ? -1 : p + v) > 0;

查询的工作原理如下:

    Select-1时,
  • B生成true;否则,如果1A则生成true0为假时生成A
  • Aggregate会检查-1, 0, 1中的这个数字列表。如果它看到-1,则汇总的结果为-1。否则,聚合的结果是正值的总和。
  • 最后的比较确保至少有一个AB

答案 1 :(得分:1)

我建议您使用类似于我对Linq All on empty collection的回答:

unset($_SESSION['user']['login'];)

它利用了var result = MyList.Max(x => B(x) ? (int?)2 : A(X) ? (int?)1 : (int?)0) == 1; 方法的工作原理

(A)如果序列为空,则返回Max<int?>
(B)如果至少有一个元素与B匹配,则结果为null
(C)如果至少有一个元素与B匹配且匹配A,则结果为2
(D)否则结果为1

所以我们简单检查案例(C)。

答案 2 :(得分:0)

试试这个:

MyList.All(x => MyList.Any() && A(x) && !B(x));

答案 3 :(得分:0)

为什么不在评估后检查是否有任何项目?

MyList.Where(x => A(x) && !B(x)).Any();

答案 4 :(得分:0)

如果您希望它为空集合返回false,则不应使用All()。看看documentation

  

如果源序列的每个元素都通过了测试,则为true   指定的谓词,如果序列为空则 ;否则,错误。

相反,我会尝试这样的事情:

MyList.Where(x => A(x) && !B(x)).Any();