I have an unordered_set
that stores the following struct
struct match_t{
size_t score;
size_t ci;
};
typedef std::unordered_set<match_t> uniq_t;
Now I want to store the elements of uniq_t myset;
to a vector, but in doing so, I want to copy just the score and not the entire struct
. I have seen solutions for assigning the elements using assign
or back_inserter
. I was wondering how to select just the required fields from the struct. I don't see any parameter in assign
or back_inserter
for this purpose.
Should I try overriding push_back
method for the vector or are there other methods for doing this?
EDIT 1 Do I get any performance improvements by using any of these methods instead of looping over the set and assigning the required values?
There is nothing wrong a simple for loop:
std::unordered_set<match_t> myset;
std::vector<std::size_t> myvec;
myvec.reserve(myset.size()); // allocate memory only once
for (const auto& entry : myset)
myvec.push_back(entry.score);
Alternatively, you could use std::transform
with a custom lambda:
#include <algorithm>
std::tranform(myset.cbegin(), myset.cend(), std::back_inserter(myvec),
[](const auto& entry){ return entry.score; });
Another way is to use a range library, e.g. with range-v3
#include <range/v3/view/transform.hpp>
std::vector<std::size_t> myvec = myset | ranges::view::transform(&match_t::score);
Performance-wise, you can't do anything about the linear pass over all match_t
objects. The important tweak instead is to minimize the number of allocations. As the size of the resulting std::vector
is known a priori, a call to std::vector::reserve
as shown above makes sure that no unnecessary allocation occur.