用于在列表中查找一项并验证列表不包含其他项的 LINQ 查询

本文关键字:列表 验证 包含 查询 LINQ 其他 查找 用于 一项 | 更新日期: 2023-09-27 18:37:13

到目前为止,我已经想出了这个:

list.Any(s => s.EnumIdValue == Close) && !list.Any(s => s.EnumIdValue == Reset || s.EnumIdValue == Cancel);

EnumIdValue 包含几个不同的可能值,如关闭、重置、取消、SomeOtherState 等。永远不应该有重复,但它仍然是可能的。

这完全符合我的需求。但是会有更好(更短)的方法来编写此查询吗?

用于在列表中查找一项并验证列表不包含其他项的 LINQ 查询

你的原件很好。另一个可行的变体是这样的:

var newQuery =
    list.Any(s => s.EnumIdValue == EnumIdValue.Close) &&
    list.All(s => s.EnumIdValue != EnumIdValue.Reset &&
                  s.EnumIdValue != EnumIdValue.Cancel);

英语:列表是否至少有一个Close列表中的每个项目是否不Reset也不Cancel

顺便说一下,有时格式化代码在可读性方面有很大的不同。

答案是:没有更好的方法来写它。

如果您尝试将其写入一个 lambda,则可以将s视为列表中的单个项目。如果该项目是Close,它当然不会是其他东西,因此在同一 lambda 中检查它是没有用的。如果要检查列表是否不包含其他值,则必须使用另一个表达式执行此操作。

您可以使用 HashSet 来测试集合是否至少包含每个EnumIdValue中的 1 个:

var enumIds = list.Select(s => s.EnumIdValue).ToHashSet();
return enumIds.Contains(Close) && !(enumIds.Contains(Cancel) || enumIds.Contains(Reset));
// or
return enumIds
  .Intersect(new[] { Cancel, Reset, Close })
  .SequenceEqual(new [] { Close });
// or (throws exception)
enumIds.IntersectWith(new[] { Cancel, Reset, Close })
return enumIds.Single() == Close;

如果您需要根据enumIds是否包含Close进行不同类型的检查,这将很有用。

怎么样

    var items = list.Select(s => s.EnumIdValue == Close) 
    if(items.Count==1)
    {
       //todo
    }

这是一个相当可读的替代方案:

var opts = new [] { Close, Reset, Cancel };
var desired = new [] { Close };
return list
        .Select(s => s.EnumIdValue)
        .Distinct()
        .Where(opts.Contains)
        .SequenceEqual(desired);