两个布尔值列表的逻辑或

Logical OR on two lists of boolean

我有两个 bool 列表,它们的长度始终相同。假设这是我的两个列表:

var list1 = new List<bool>() { true, false, true, false, false };
var list2 = new List<bool>() { true, true, true, false, true };

我想通过将逻辑 OR 运算符应用于任一列表中的每个相应索引来创建一个新列表。所以,如果我的两个列表是上面的,我的预期结果将是下面的。

true, true, true, false, true

现在,我可以像这样使用 for 循环轻松地做到这一点:

var result = new List<bool>();
for (int i = 0; i < list1.Count; i++)
{
    result.Add(list1[i] || list2[i]);
}

这非常有效,甚至不一定是低效的。但是在我的应用程序中,我有超过 2 个列表,有时甚至有 20 个,我需要获取所有列表的 OR

考虑到所有列表,是否有更简单的方法?

你可以试试 IEnumerable.Zip

var result = list1.Zip(list2, (first, second) => first || second);

它通过对来自两个源序列的每对元素应用逻辑或来生成结果序列。

在对 Pavel Anikhouski 的回答的评论中,您提到了多个列表。我将使用 Aggregate 扩展方法扩展该答案。

public static IEnumerable<bool> OrBooleanSequences(IEnumerable<IEnumerable<bool>> source)
{
    return source.Aggregate((a, b) => a.Zip(b, (x, y) => x || y));
}

只需将列表作为数组或其他可枚举传递,然后具体化结果。

var list1 = new List<bool>() { true, false, true, false, false, false };
var list2 = new List<bool>() { true, true, true, false, true, false };
var list3 = new List<bool>() { false, true, false, true, true, false };

var result = ZipMultiple(new[] { list1, list2, list3 }).ToList();

编辑

在@Theodor Zoulias 的推荐下,我重命名了上面的方法。我选择了OrBooleanSequences。不过,这个名称相当随意,所以如果您使用它并且想给它起一个对您来说更有意义的其他名称,那么您的功能就会更强大。

因此,这导致了一个更通用的方法,我将其称为 AggregateSequences,它将是一个高阶函数,采用描述如何执行聚合的函数(resultSelector此处和 Zip 重载)。

public static IEnumerable<TSource> AggregateSequences<TSource>(IEnumerable<IEnumerable<TSource>> source, Func<TSource, TSource, TSource> resultSelector)
{
    return source.Aggregate((a, b) => a.Zip(b, resultSelector));
}

...您会将逻辑或运算作为 lambda 传递给它。

var result = AggregateSequences(new[] { list1, list2, list3 }, (x, y) => x || y).ToList();

这可以用于其他操作,例如对列表中的元素求和:

var list1 = new List<int>() { 1, 2, 3 };
var list2 = new List<int>() { 4, 5, 6 };
var list3 = new List<int>() { 7, 8, 9 };

var result = AggregateSequences(new[] { list1, list2, list3 }, (x, y) => x + y).ToList();

结果:

[ 12, 15, 18 ]

当然,这种方法只是一种变体。 ZipAggregate 有多个可以组合的重载。我不确定所有组合是否都有意义,但我会把它留给 reader.

作为练习

假设您有一个列表列表:

var listsOfLists = new List<IEnumerable<bool>>
{
    new List<bool>() { true, false, true, false, false },
    new List<bool>() { true, true, true, false, true },
    new List<bool>() { true, false, true, false, false },
    new List<bool>() { true, false, true, true, true }
};

使用 Linq,您可以结合使用 AggregateZip

var combinedResults = listsOfLists
    .Aggregate((a, b) => a
        .Zip(b, (aElement, bElement) => aElement || bElement)
     );

Zip 会将两个选定列表中的每个元素配对,运行 将 "or" 运算符与这些元素对配对,从而为您提供一个新的 bool 列表。结果列表将用于下一个聚合操作。