Bartlomiej Lewandowski
Bartlomiej Lewandowski

Reputation: 11180

Create new sorted vector without duplicates

So far i have this function:

std::vector<int> f(std::vector& v)
{
    std::vector<int> result;
    for(unsigned x = 0; x < v.size(); x++)
    {
        std::vector<int>::iterator location = std::find(result.begin(),result.end(),v[x]);
        if(location == result.end())
        {
            result.push_back(this->v[x]);
        }
    }
    std::sort(result.begin(),result.end());
    return result;
}

This function returns a sorted vector of elements from v without duplicates.

Is there a more compact way of writing this? I've read about std::unique,but this involves editing the vector which i cannot do.

Upvotes: 2

Views: 1297

Answers (2)

syam
syam

Reputation: 15059

I've read about std::unique,but this involves editing the vector which i cannot do.

Make a copy first! Then you can use unique/erase in the usual way. In C++03 you would write:

std::vector<int> f(const std::vector<int>& v)
//                 ^^^^^ you won't modify v, so make it obvious!
{
    std::vector<int> result(v); // copy the vector
    std::sort(result.begin(),result.end()); // sort it first so that std::unique can work
    std::erase(std::unique(result.begin(),result.end()), result.end()); // just keep the unique elements
    return result;
}

If you use C++11 then you can take advantage of move semantics and pass-by-value arguments (it is more efficient when you pass an rvalue to your function and is just as efficient for lvalues), which also allows you to directly modify the argument:

std::vector<int> f(std::vector<int> v)
//                 ^^^^^^^^^^^^^^^^ pass by value
{
    std::sort(v.begin(),v.end()); // sort it first so that std::unique can work
    std::erase(std::unique(v.begin(),v.end()), v.end()); // just keep the unique elements
    return v;
}

Thanks @DavidBrown and @chris, I tend to overlook this C++11 idiom since I'm not yet used to it.

Upvotes: 3

Jerry Coffin
Jerry Coffin

Reputation: 490228

Since you're copying the vector anyway, just do the copy, then sort and unique the result:

std::vector<int> f(std::vector<int> v) { 
    using std::begin;
    using std::end;

    std::sort(begin(v), end(v));
    v.erase(std::unique(begin(v), end(v)), end(v));
    return v;
}

Upvotes: 6

Related Questions