I'd like to find the unique number in std::vector, but I see an error that I don't understand. Can someone take a look, and explain me what is going wrong? Optionally if you have a better solutions, please, share.
#include <iostream>
#include <vector>
#include <algorithm>
float find_uniq(const std::vector<float> &v)
{
if(v[0] == v[1]) {
auto it = std::find_if_not(v.begin(), v.end(), v[0]);
return *it; }
else if(v[0] == v[2]) {
auto it = std::find_if_not(v.begin(), v.end(), v[0]);
return *it; }
else if(v[1] == v[2]) {
auto it = std::find_if_not(v.begin(), v.end(), v[1]);
return *it; }
};
int main()
{
std::vector<float> m = {4, 4, 3, 4, 4};
std::cout<< find_uniq(m);
return 0;
}
Here is an error:
error: expression cannot be used as a function
{ return !bool(_M_pred(*__it)); }
CodePudding user response:
You can use std::map
to count the frequencies of all the input numbers. A frequency of one indicate that the number is unique.
Below is the program which uses this logic.
#include <iostream>
#include <map>
#include <optional>
#include <vector>
#include <algorithm>
std::vector<float> find_uniq(const std::vector<float> &v)
{
std::map<float, int> freqCount;
for(size_t i = 0; i < v.size(); i) {
freqCount[v[i]] ;
}
std::vector<float> result;
for(const auto& [key, val] : freqCount) {
if(val == 1) result.push_back(key);
}
return result;
}
int main()
{
std::vector<float> m = {4, 4, 3, 4, 4, 3, 1, 2, 3, 4, 5};
auto result = find_uniq(m);
if(result.size() > 0) {
for(const auto& ele : result) {
std::cout << ele << ", ";
}
} else {
std::cout << "No unique values in the input vector.\n";
}
return 0;
}
Here is the output:
Unique values: 1, 2, 5,
CodePudding user response:
The third parameter of std::find_if[_not]
is not an element, but a predicate, i.e. something you can pass a dereferenced iterator to via the call operator and that yields something that is convertible to bool
. std::find_if_not
will return the iterator to the first element where the this functor yields false
, or the end iterator, if there's no such element.
You could e.g. replace
auto it = std::find_if_not(v.begin(), v.end(), v[0]);
with
auto it = std::find_if_not(v.begin(), v.end(), [x = v[0]](float v) { return (x == v); });
to fix the syntax error.
Note that there's another issue in your code though:
std::find_if_not
can yield the end iterator and dereferencing this operator is undefined behaviour. You're doing this though in
return *it;
Note: The whole approach seems more complex than necessary. You could simply create a std::map<float, size_t>
counting the number of occurances of each element and then search this map for mappings with the value 1
:
float find_uniq(const std::vector<float>& values)
{
std::map<float, size_t> frequencies;
for (auto value : values)
{
frequencies[value];
}
for (auto [key, value] : frequencies)
{
if (value == 1)
{
return key;
}
}
throw std::runtime_error("No unique element found");
}