两个布尔值列表的逻辑或
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 ]
当然,这种方法只是一种变体。 Zip
和 Aggregate
有多个可以组合的重载。我不确定所有组合是否都有意义,但我会把它留给 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,您可以结合使用 Aggregate
和 Zip
var combinedResults = listsOfLists
.Aggregate((a, b) => a
.Zip(b, (aElement, bElement) => aElement || bElement)
);
Zip
会将两个选定列表中的每个元素配对,运行 将 "or" 运算符与这些元素对配对,从而为您提供一个新的 bool 列表。结果列表将用于下一个聚合操作。
我有两个 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 ]
当然,这种方法只是一种变体。 Zip
和 Aggregate
有多个可以组合的重载。我不确定所有组合是否都有意义,但我会把它留给 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,您可以结合使用 Aggregate
和 Zip
var combinedResults = listsOfLists
.Aggregate((a, b) => a
.Zip(b, (aElement, bElement) => aElement || bElement)
);
Zip
会将两个选定列表中的每个元素配对,运行 将 "or" 运算符与这些元素对配对,从而为您提供一个新的 bool 列表。结果列表将用于下一个聚合操作。