[英]How to check if a `std::vector<bool>` is true at multiple indexes simultaneously?
我有一个大小为 N 的std::vector<bool>
和一个可变大小的std::vector<std::size_t>
,其中包含[0, N)
中的索引。 检查第一个向量在第二个向量给出的所有索引处是否为真的惯用方法是什么?
我可能天真的解决方案是:
auto all_true(
std::vector<bool> const& bools, std::vector<std::size_t> const& indexes)
-> bool {
auto res = true;
for (auto index : indexes) {
res = res and bools[index];
}
return res;
}
An idiomatic (though not necessarily efficient ) way to do this would be to use the std::all_of
STL function , using a predicate that simply returns the value of the Boolean vector at the index specified by each value in the size_t
vector.
这是一个大纲/演示:
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
bool all_true(const std::vector<bool>& data, const std::vector<size_t>& test)
{
return std::all_of(test.begin(), test.end(), [&data](size_t n) { return data[n]; });
}
int main()
{
std::vector<bool> bools{ true, true, true, true, false, false, true, false, true, false };
std::vector<size_t> test1{ 0, 1, 2, 3, 6, 8 }; // all true
std::vector<size_t> test2{ 0, 1, 2, 4, 7, 9 }; // some false
std::cout << "Test1: " << all_true(bools, test1) << "\n";
std::cout << "Test2: " << all_true(bools, test2) << "\n\n";
// Just to show that the order doesn't matter ...
std::cout << "After shuffling ...\n";
std::random_device rdev;
std::mt19937 rgen(rdev());
std::shuffle(test1.begin(), test1.end(), rgen);
std::shuffle(test2.begin(), test2.end(), rgen);
std::cout << "Test1: " << all_true(bools, test1) << "\n";
std::cout << "Test2: " << all_true(bools, test2) << "\n";
return 0;
}
不要认为你的代码不是惯用的。
基于for()
的范围可以处理这种情况。 特别是如果您正在编写一个名为 function 来封装它。
auto allTrue(std::vector<bool> const& data, std::vector<std::size_t> const& indexs) -> bool
{
for (auto index: indexs) {
if (!data[index]) {
return false;
}
}
return true;
}
基于预范围的迭代器我会说使用使用迭代器的标准 function。
auto allTrue(std::vector<bool> const& data, std::vector<std::size_t> const& indexs) -> bool
{
return std::all_of(std::begin(indexs), std::end(indexs),
[&data](std::size_t i){return data[i];}
);
}
也许:如果您不打算将其包装在 function 中,那么在代码中直接使用此std::all_of()
function 使其更易于阅读,然后使用它。 但是,如果您正在编写 function 无论如何都要使用基于的范围。
或者如果你有 C++20
auto allTrue(std::vector<bool> const& data, std::vector<std::size_t> const& indexs) -> bool
{
return std::ranges::all_of(indexs, [&data](std::size_t i){return data[i];});
}
另一种选择是std::accumulate
。 如果结果类型和输入std::vector
元素类型相同,则可以改用(更有效的) std::reduce
。 但是,在这种情况下,您需要(某种程度上)将size_t
s(指向bool
s 的std::vector
的索引)累积到bool
结果中:
#include <iostream>
#include <numeric>
#include <vector>
int main() {
const std::vector<bool> bools{true, true, false, true, true};
const std::vector<size_t> i1{1, 4, 3, 0}; // true && true && true && true
const std::vector<size_t> i2{0, 2, 4, 3}; // true && false && true && true
const auto and_by_idx{
[&bools](bool acc, size_t idx) { return acc && bools[idx]; }};
std::cout << std::boolalpha
<< std::accumulate(i1.begin(), i1.end(), true, and_by_idx) << '\n'
<< std::accumulate(i2.begin(), i2.end(), true, and_by_idx) << '\n';
}
不过,我不会将任何 C++ 解决方案称为惯用的。 其他一些语言有更短更优雅的表达方式,比如 Python 及其all()
。
bools = (True, True, False, True, True)
i1 = (1, 4, 3, 0) # True && True && True && True
i2 = (0, 2, 4, 3) # True && False && True && True
print(all(bools[i] for i in i1))
print(all(bools[i] for i in i2))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.