I was wondering if there was a quick way to find out if all elements in a vector are false or true? Like instead of checking each element using a loop?
I'd take advantage of the new algorithms for clarity:
// all true
std::all_of(vec.begin(), vec.end(), [](bool v) { return v; });
// all false
std::all_of(vec.begin(), vec.end(), [](bool v) { return !v; });
std::none_of(vec.begin(), vec.end(), [](bool v) { return v; });
You can't find out if all the elements in a vector are true without actually checking every element of the vector. Best-case, you reinterpret the memory differently and check more than 1 element at a time, but you still have to check everything until you find one that fails your test.
[](bool v) { return v; }
, you can also #include <functional>
and do std::all_of(vec.begin(), vec.end(), std::identity);
–
Maclay std::identity
is available only in c++20. –
Everrs Easiest IMO is the free find
function
if (std::find(begin(v), end(v), true) == end(v)) // All false
You can also use std::accumulate()
:
int sum = std::accumulate(std::begin(v), std::end(v), 0);
if (sum == v.size()) {
// All true
}
else if (sum) {
// Any true, any false
}
else {
// All false
}
if (accu..() == v.size())
–
Sheff A more efficient option for large vectors is to replace your vector<bool>
with a vector<bitset>
. Then you can simply combine the any_of()
algorithm with a lambda function invoking the bitset
member function any()
(or similarly for all_of()
and all()
).
int n = 2000000000, i = 623;
vector<bitset<256>> bits((n + 255) / 256);
bits[i >> 8][i & 0xFF] = true;
cout << bits[i >> 8][i & 0xFF] << endl;
if (any_of(bits.begin(), bits.end(),
[](const bitset<256>& bs) { return bs.any(); })) {
cout << "at least one bit set" << endl;
}
for (auto& bs : bits) {
bs.set();
}
if (all_of(bits.begin(), bits.end(),
[](const bitset<256>&bs) { return bs.all(); })) {
cout << "all bits set" << endl;
}
In my timing tests with 2 billion elements (release build VS2022), either any_of()
or all_of()
above took 20ms (faster if any_of()
breaks out early). Whereas with vector<bool>
they required 2200ms. About 100x speedup. Setting all bits took 36ms, as compared to 1930ms for a vector<bool>
, about 50x speedup.
The interface is slightly messy so you can wrap it in a template class if you want to to clean it up:
template <size_t bits_per_bitset, int lg_bits_per_bitset>
class dynamic_bitset {
public:
dynamic_bitset(int n)
: v((n + bits_per_bitset - 1)/ bits_per_bitset) { }
constexpr bool operator[](int i) const {
return v[i >> lg_bits_per_bitset][i & ((1 << lg_bits_per_bitset) - 1)];
}
auto operator[](int i) {
return v[i >> lg_bits_per_bitset][i & ((1 << lg_bits_per_bitset) - 1)];
}
bool any() {
return any_of(v.begin(), v.end(),
[](const std::bitset<bits_per_bitset>& bs) { return bs.any(); });
}
bool all() {
return all_of(v.begin(), v.end(),
[](const std::bitset<bits_per_bitset>& bs) { return bs.all(); });
}
void set() { for (auto& bs : v) bs.set(); }
void reset() { for (auto& bs : v) bs.reset(); }
void flip() { for (auto& bs : v) bs.flip(); }
private:
std::vector<std::bitset<bits_per_bitset>> v;
};
Now using it is as simple as this:
int n = 2000000000, i = 623;
dynamic_bitset<256, 8> bits(n);
bits[i] = true;
cout << bits[i] << endl;
if (bits.any()) {
cout << "at least one bit set" << endl;
}
bits.set();
if (bits.all()) {
cout << "all bits set" << endl;
}
If I increase the template parameters, it gets a bit faster, but increases the wasted space if n
is not divisible by bits_per_bitset
. In my experiments there were no further returns beyond <1024,10>
, which occupies a minimum of 32 words of 32 bits each.
You can add a bunch of other operations to dynamic_bitset
easily including push_back()
, bitwise operators, begin()
/end()
, etc.
This requires looping, but will at least take advantage of short-ciruiting behavior.
bool all = true;
std::vector<bool>::iterator it = myVec.begin();
while(all && it != myVec.end()) // Stops early if it hits a false
{
all &= *it;
++it;
}
If all
is true
, all elements in the vector were true. If all
is false, at least one element was not true
.
all
is false, at least one element was not true
". (or at least one element was false
) –
Untoward all
function. The complement any
would tell you if all elements are false
, which would be similar to this code but with a few slight modifications. –
Unexacting I also agree that worst case one will have to check every individual element but for all other cases I suggest rephrasing the question:
Are all elements in my collection equal? If so, to what value.
This will return early in both cases and you are done. Else one additionally will have to check the value of the element (true or false).
For this I would suggest to look here.
I want to generalize my answer a bit more: This can be done with any N mutually exclusive predicates A1, ... , AN that I want to check for my collection. For this I will need a function that, given an element of my collection, returns some identifier of the predicate Ai that holds for the element (and a way to check the predicates for equality).
Then again I can apply the above scheme.
I think the most efficient would be:
if(v.find(v.begin(), v.end(), true) == v.end())
// All false
if(v.find(v.begin(), v.end(), false) == v.end())
// All true
© 2022 - 2024 — McMap. All rights reserved.
bitset
, but look intoany_of
andall_of
. – Extremetrue\false
as1\0
, try turning it into ak-th order statistic
problem. Find just the first and last values inO(log.n)
time. If they're same, you know they are all one value. – RestitutionO(log.n)
. Without specialized structures it would beO(n)
. Worth a thought if you're really after the fastest possible way but perhaps overkill otherwise. – Restitution