Reputation: 11180
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
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
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