adding elements of a vector to an unordered set - c++

Is there an easy way to add all the elements of a vector to an unordered_set? They are of the same type. Right now, I am using a for loop and was wondering if there is a better way to do it

If you're constructing the unordered_set then:
std::vector<int> v;
std::unordered_set<int> s(v.begin(), v.end());

Forgive me if my syntax has any minor bugs, but you can try the std::copy function, its meant for this purpose.
std::vector<int> v;
std::unordered_set<int> s;
std::copy(v.begin(),v.end(),std::inserter(s,s.end()));

Related

Iterate over a vector and create another vector based on elements

Maybe a stupid/naive question, but if I have a vector of vectors like this:
std::vector<std::vector<Element> vec
what is the most efficient way to create another vector from this one which containes all the sizes of elements from the previous vector:
std::vector<std::size_t> newVector = {vec[0].size(), ..., vec[vec.size()-1].size()}
is there a function for stuff like this?
Thanks in advance.
There might be a 1-liner approach using something from <algorithm> or fancy accumlator/transform routine. But it's hard to beat the readability of this:
std::vector<std::size_t> newVector;
for (const auto& item : vec) {
newVector.push_back(item.size());
}
If you prefer the hip way to do it, which some people like, but in my opinion makes for rather unreadable code.
vector<int> newVec(vec.size());
std::transform(vec.begin(), vec.end(), newVec.begin(), [](vector<int>& v) {return v.size(); });

Why I could use push_back in map but not the back_inserter in set?

The 11th chapter (about associative containers) of C++ Primer 5th says:
The associative containers do not support the sequential-container position-specific operations, such as push_front or back. Because the elements are stored based on their keys, these operations would be meaningless for the associative containers.
However, after I practice two exercises, I am confused:
Given a map<string, vector<string>>, one is asked to add a vector<int> to a given key, my (working) solution is:
using Map = map<string, vector<string>>;
Map my_map;
for(string ln; cin >> ln)
for(string cn; cin >> cn)
my_map[ln].push_back(cn);
However in the second exercise, assuming c is a multiset of strings and v is a vector of strings, is copy(v.begin(), v.end(), back_inserter(c)); legal or illegal?
When I use it, I got this error:
error: 'class std::multiset >' has no member named 'push_back'`
What I have known is back_inserter doesn't work since there's no push_back.
my_map[ln].push_back(cn) does not call push_back on the map (my_map), it calls push_back on the maps mapped_type which is vector<string> - you access this with operator[] (my_map[ln]).
Your statement my_map[ln].push_back(cn) is essentially equivalent to:
vector<string>& v = my_map[ln];
v.push_back(cn);
You do not use push_back on map. You are using it on a vector of strings contained in map.
back_inserter uses push_back internally and associative containers lack such method, so it will not work with it.
You could use std::inserter instead, that will call std::multiset::insert
std::vector<std::string> v {"aaa", "bbbb", "ccc"};
std::multiset<std::string> m;
std::copy(v.begin(), v.end(), std::inserter(m, m.end()));
for (const auto & x : m)
std::cout << x << "\n";
Live on coliru
Your solution doesn't push_back to an associative container, but to a vector stored in that. That's something different.
As the primer says, a multiset doesn't have the sequential push_back method, so you can't use std::copy(...,...,std::back_inserter(..)) with it.

Extract a subvector from a vector with iterator

i'm trying to extract a subvector of int from another subvector of int using iterator with this code :
std::vector<int> Original;
std::vector<int> NewVec;
NewVec(Original.begin(), Original.begin()+5);
and this doesn't work, only if i declare NewVec in the same line of extraction like that :
std::vector<int> NewVec(Original.begin(), Original.begin()+5);
So, is it possible to use NewVec such that its declaration is before its construction ?
Thanks.
If you want to assign a subrange to an existing std::vector you can use the assign() member:
NewVec.assign(Original.begin(), Original.begin() + 5);
Of course, this assumes that Original has at least 5 elements.
You can use std::copy:
NewVec.reserve(5);
std::copy(std::begin(Original), std::begin(Original)+5,
std::back_inserter(NewVec));
Or std::vector::assign:
NewVec.assign(std::begin(Original), std::begin(Original)+5);

Checking for Item in std::vector<std::vector<std::string>> Using std::find

I have the following object
std::vector<std::vector<std::string>> vectorList;
Then I add to this using
std::vector<std::string> vec_tmp;
vec_tmp.push_back(strDRG);
vec_tmp.push_back(strLab);
if (std::find(vectorList.begin(), vectorList.end(), vec_tmp) == vectorList.end())
vectorList.push_back(vec_tmp);
The std::vector<std::string>s contained vectorList are only ever 2-dimensional and there are no duplicates. This works great, but I now only want to check if vectorList contains an item that index zero equal to the current strDrg. In C# I would not even be thinking about this, but this does not seem straight forward using C++. How can I find if a vector exists in vectorList where strDrg already exists in vectorList.at(i)[0]?
Note: I can use boost.
Use find_if with a lambda:
std::find_if(vectorList.begin(), vectorList.end(),
[&strDrg](const std::vector<std::string>& v) { return v[0] == strDrg; });
It seems you don't need the full power of vector for you inner elements. Consider using:
std::vector<std::array<std::string, 2>>
instead.
For doing exactly what you asked, std::find_if with a lambda as #chris proposed in comments is the best:
std::find_if(ob.begin(), ob.end(),
[&](const auto x){return x[0] == strDRG;});
// Replace auto with "decltype(ob[0])&" until
//you have a C++1y compiler. Might need some years.
But if you only ever have exactly two elements, consider using a std::array<...>, a std::pair<...> or a std::tuple<...> instead of the inner vector.
For tuple and pair, you need to access the first element differently:
pair : member first
tuple: use get<0>(x);

Get all stl vector elements greater than a value

I would like to know how can I find the list of a stl vector elements that have value verifying a certain condition. For example if I have a vector of int values
vector<int> V;
and I want to get all the elements that are greater than 5.
Thanks in advance.
You'd std::copy_if() if the values:
std::vector<int> target;
std::copy_if(v.begin(), v.end(), std::back_inserter(target),
std::bind(std::less<int>(), 5, _1));