Home > Enterprise >  How to find the unique number in std::vector
How to find the unique number in std::vector

Time:09-18

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");
}
  • Related