How can I sort an STL map by value? - c++

How can I implement STL map sorting by value?
For example, I have a map m:
map<int, int> m;
m[1] = 10;
m[2] = 5;
m[4] = 6;
m[6] = 1;
I'd like to sort that map by m's value. So, if I print the map, I'd like to get the result as follows:
m[6] = 1
m[2] = 5
m[4] = 6
m[1] = 10
How can I sort the map in this way? Is there any way that I can deal with the key and value with sorted values?

Dump out all the key-value pairs into a set<pair<K, V> > first, where the set is constructed with a less-than functor that compares the pair's second value only. That way, your code still works even if your values aren't all distinct.
Or dump the key-value pairs into a vector<pair<K, V> >, then sort that vector with the same less-than functor afterwards.

You can build a second map, with the first map's values as keys and the first map's keys as values.
This works only if all values are distinct. If you cannot assume this, then you need to build a multimap instead of a map.

I wonder how can I implement the STL map sorting by value.
You can’t, by definition. A map is a data structure that sorts its element by key.

You should use Boost.Bimap for this sort of thing.

Based on #swegi's idea, I implemented a solution in c++11 using a multimap:
map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
multimap<int, int> mm;
for(auto const &kv : m)
mm.insert(make_pair(kv.second, kv.first)); // Flip the pairs.
for(auto const &kv : mm)
cout << "m[" << kv.second << "] = " << kv.first << endl; // Flip the pairs again.
Code on Ideone
I also implemented a C++11 solution based on #Chris' idea using a vector of pairs. For correct sorting, I provide a lambda expression as comparison functor:
map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
using mypair = pair<int, int>;
vector<mypair> v(begin(m), end(m));
sort(begin(v), end(v), [](const mypair& a, const mypair& b) { return a.second < b.second; });
for(auto const &p : v)
cout << "m[" << p.first << "] = " << p.second << endl;
Code on Ideone
The first solution is more compact, but both solutions should have roughly the same performance. Inserting into a multimap is of O(log n), but this has to be done for n entries, resulting in O(n log n). Sorting the vector in the second solution also results in O(n log n).
I also gave a try to #Chris' idea on using a set of pairs. However, it won't work if the values aren't all distinct. Using a functor that compares only the pair's second element doesn't help. If you first insert make_pair(1, 1) into the set and then try to insert make_pair(2, 1), then the second pair won't be inserted, because both pairs are seen as identical by that set. You can see that effect here on Ideone.

I've just done a similar question in my c++ book. The answer I came up with might not be very efficient though:
int main()
{
string s;
map<string, int> counters;
while(cin >> s)
++counters[s];
//Get the largest and smallest values from map
int beginPos = smallest_map_value(counters);
int endPos = largest_map_value(counters);
//Increment through smallest value to largest values found
for(int i = beginPos; i <= endPos; ++i)
{
//For each increment, go through the map...
for(map<string, int>::const_iterator it = counters.begin(); it != counters.end(); ++it)
{
//...and print out any pairs with matching values
if(it->second == i)
{
cout << it->first << "\t" << it->second << endl;
}
}
}
return 0;
}
//Find the smallest value for a map<string, int>
int smallest_map_value(const map<string, int>& m)
{
map<string, int>::const_iterator it = m.begin();
int lowest = it->second;
for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
{
if(it->second < lowest)
lowest = it->second;
}
return lowest;
}
//Find the largest value for a map<string, int>
int largest_map_value(const map<string, int>& m)
{
map<string, int>::const_iterator it = m.begin();
int highest = it->second;
for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
{
if(it->second > highest)
highest = it->second;
}
return highest;
}

Create another map, provide a less() function based on the value not key, AND the function should return true if the value1 <= value2 (not strictly < ). In this case, elements with non-distinct values can be sorted as well.

I have found this in thispointer. The example sorts a std::map< std::string,int> by all the int values.
#include <map>
#include <set>
#include <algorithm>
#include <functional>
int main() {
// Creating & Initializing a map of String & Ints
std::map<std::string, int> mapOfWordCount = { { "aaa", 10 }, { "ddd", 41 },
{ "bbb", 62 }, { "ccc", 13 } };
// Declaring the type of Predicate that accepts 2 pairs and return a bool
typedef std::function<bool(std::pair<std::string, int>, std::pair<std::string, int>)> Comparator;
// Defining a lambda function to compare two pairs. It will compare two pairs using second field
Comparator compFunctor =
[](std::pair<std::string, int> elem1 ,std::pair<std::string, int> elem2)
{
return elem1.second < elem2.second;
};
// Declaring a set that will store the pairs using above comparision logic
std::set<std::pair<std::string, int>, Comparator> setOfWords(
mapOfWordCount.begin(), mapOfWordCount.end(), compFunctor);
// Iterate over a set using range base for loop
// It will display the items in sorted order of values
for (std::pair<std::string, int> element : setOfWords)
std::cout << element.first << " :: " << element.second << std::endl;
return 0;
}

One thing that could be done in some scenarios, is using a vector<pair<int, int>> rather than using maps<int, int>. In this way you lose the benefits of using map, such as the less lookup time but you can directly use comparator function with vector<pair<int, int>>
bool compare(pair<int, int> a, pair<int, int> b)
{
return (a.second < b.second);
}

Recently had to do this. I ended up using pointers...
Quick Benchmark Results
#include <iostream>
#include <type_traits>
#include <algorithm>
#include <map>
#include <vector>
using map_t = std::map<int,int>;
const map_t m
{
{ 5, 20 },
{ -18, 28 },
{ 24, 49 },
{ 17, 27 },
{ 23, 46 },
{ 8, 16 },
{ -13, 11 },
{ -22, 32 },
{ 12, 45 },
{ -2, 19 },
{ 21, 11 },
{ -12, 25 },
{ -20, 8 },
{ 0, 29 },
{ -5, 20 },
{ 13, 26 },
{ 1, 27 },
{ -14, 3 },
{ 19, 47 },
{ -15, 17 },
{ 16, 1 },
{ -17, 50 },
{ -6, 40 },
{ 15, 24 },
{ 9, 10 }
};
template<typename T>
void sort_values_using_vector(T const& m)
{
using map_t = T;
using sort_t = std::vector<std::pair<typename map_t::key_type,
typename map_t::mapped_type>>;
sort_t sorted{ m.begin(), m.end() };
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs.second < rhs.second;
});
}
template<typename T>
void sort_values_using_multimap(T const& m)
{
using map_t = T;
using sort_t = std::multimap<typename map_t::mapped_type,
typename map_t::key_type>;
sort_t sorted;
for (auto const& kv : m)
{
sorted.insert(std::make_pair(kv.second, kv.first));
}
}
template<typename T>
void sort_values_using_ptrs(T const& m)
{
using map_t = T;
using ptr_t = std::add_pointer_t
<std::add_const_t<typename map_t::value_type>>;
using sort_t = std::vector<ptr_t>;
sort_t sorted;
sorted.reserve(m.size());
for (auto const& kv : m)
{
sorted.push_back(std::addressof(kv));
}
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs->second < rhs->second;
});
}
template<typename T>
void sort_values_using_refs(T const& m)
{
using map_t = T;
using ref_t = std::reference_wrapper
<std::add_const_t<typename map_t::value_type>>;
using sort_t = std::vector<ref_t>;
sort_t sorted{ m.begin(), m.end() };
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs.get().second < rhs.get().second;
});
}
static void copy_to_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_vector(m);
}
}
BENCHMARK(copy_to_vector);
static void copy_flipped_to_multimap(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_multimap(m);
}
}
BENCHMARK(copy_flipped_to_multimap);
static void copy_ptrs_to_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_ptrs(m);
}
}
BENCHMARK(copy_ptrs_to_vector);
static void use_refs_in_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_refs(m);
}
}
BENCHMARK(use_refs_in_vector);

This code uses custom sorting function to sort map by values
// Comparator function to sort pairs
// according to value
bool comp(pair<int, int>& a,
pair<int, int>& b)
{
return a.second < b.second;
}
// Function to sort the map according
// to value in a (key-value) pair
void customSort(map<int, int>& m)
{
vector<pair<int, int>> a;
for(auto x:m)
a.push_back(make_pair(x.first,x.second));
sort(a.begin(), a.end(), comp);
for (auto x:a) {
cout << x.first<<" "<<x.second<<endl;
}
}

Related

Finding a key-value-pair within a std::multimap with key of type int

I have a std::multimap<int, X*> where X is a user-defined type. I want to find a specific key-value-pair within this multimap (i.e. an iterator pointing to this pair).
(A) Complete Example:
#include <map>
#include <algorithm>
class X {};
int main()
{
X myX;
std::multimap<int, X*> myMap;
auto it = std::find(myMap.begin(), myMap.end(), std::make_pair(5, &myX));
return 0;
}
However, this does not compile (gcc 12.2.1 with -std=gnu++2a):
no match for ‘operator==’ (operand types are ‘std::pair<const int, X*>’ and ‘const std::pair<int, X*>’)
So it seems to me somehow int gets converted to const int.
(B) Using std::find_if with a lamdba function with const int, the code compiles:
auto it = std::find_if(myMap.begin(), myMap.end(), [myX](std::pair<const int, X*>& node){ return 5 == node.first && (&myX) == node.second; } );
Questions:
Why is the type of the keys in the multimap const int and not int?
How to fix it in a more natural way than using a (complex) lambda function like in (B) or by first looking up by key and then searching within its values (as described by Igor Tandetnik in the comments)?
Why is the type of the keys in the multimap const int and not int?
Because the Key in all standard maps is immutable.
How to fix it in a more natural way than using a (complex) lambda function like in (B) or by first looking up by key and then searching within its values?
Here's a simplified example that doesn't use X* but X in the map:
#include <algorithm>
#include <iostream>
#include <map>
struct X {
bool operator==(const X& rhs) const { return m_value == rhs.m_value; }
int m_value;
};
int main() {
std::multimap<int, X> myMap{
{4, {1}}, {5, {2}}, {6, {3}}, {4, {4}}, {5, {5}}, {6, {6}}
};
// get the range of _Key_s equal to 5
auto [first, last] = myMap.equal_range(5);
// the lambda - here used to find the first entry with the _Value_ `X{2}`
auto cond = [](auto&& pair) { return pair.second == X{2}; };
if (auto it = std::find_if(first, last, cond); it != last)
{
auto& [k, v] = *it;
std::cout << k << ' ' << v.m_value << '\n';
}
}
Demo
If many Values may be found, just put the find_if in a loop:
for(;(first = std::find_if(first, last, cond)) != last; ++first) {
auto& [k, v] = *first;
std::cout << k << ' ' << v.m_value << '\n';
}
Demo

Initialising a 2d map c++

I have been thinking lately about 2d structures (of integers) in which their sizes can grow dynamically. I came across 'map' which I think that it meets my following need: Essentially, what I want is to check whether a random entry has been initialized or not (do something if it has not been initialized yet).
int main(){
int int1, int2;
std::map<int,std::map<int,int>> my_map;
cout << "Enter two integers separated by space: ";
cin >> int1 >> int2;
if(has my_map[int1][int2] not been initialized){
do something
}
}
I am hoping that such functionality is available with C++.
If what you mean by checking whether an entry "has been initialized" is checking that a pair of keys has a value assigned to them -- one key for the outer map and one for the inner map -- you can test contents of a map of maps as below:
bool contains_keys(const std::map<int, std::map<int, int>>& map_of_maps, int key1, int key2) {
auto iter = map_of_maps.find(key1);
if (iter == map_of_maps.end()) {
return false;
}
return iter->second.find(key2) != iter->second.end();
}
However, I question whether a map of maps is really what you want. If what you want is just a mapping from two keys to a single value, a more direct and space efficient implementation is to use an std::map with an std::tuple or std::pair as the key type.
Tuples version below.
#include <map>
#include <tuple>
#include <iostream>
int main()
{
std::map<std::tuple<int, int>, int> map_of_pairs;
map_of_pairs[{42, 17}] = 3;
bool contains_42_17 = (map_of_pairs.find({ 42, 17 }) != map_of_pairs.end());
bool contains_67_23 = (map_of_pairs.find({ 67, 23 }) != map_of_pairs.end());
std::cout << ((contains_42_17) ? "yes\n" : "no\n");
std::cout << ((contains_67_23) ? "yes\n" : "no\n");
}
Also unless you actually need the above to be ordered, consider an unordered_map.
You could write a function that first checks the outer map for key1, then if an inner map exists with that key, check the inner map for key2.
bool nested_contains(std::map<int,std::map<int,int>> const& my_map, int key1, int key2)
{
auto itOuter = my_map.find(key1);
if (itOuter == my_map.end())
return false;
return itOuter->second.contains(key2);
}
Then use it like
int main()
{
int int1, int2;
std::map<int,std::map<int,int>> my_map;
std::cout << "Enter two integers separated by space: ";
std::cin >> int1 >> int2;
if(nested_contains(my_map, int1, int2)){
// do something
}
}
You can quickly do it creating a custom function using the find method.
In that case the algorithm is suitable for being generic.
template<typename T>
bool contains_keys_cpp_20(std::map<T, std::map<T, T>> const& nested_map, T key1, T key2)
{
auto pair = nested_map.find(key1);
return (pair != nested_map.end()) && (pair->second.contains(key2));
}
template<typename T>
bool contains_keys_cpp_17(std::map<T, std::map<T, T>> const& nested_map, T key1, T key2)
{
auto pair = nested_map.find(key1);
return (pair != nested_map.end()) && (pair->second.find(key2) != pair->second.end());
}
int main()
{
{
std::map<int, std::map<int, int>> my_map;
my_map[1] = { { 2, 1} };
bool result = contains_keys_cpp_17(my_map, 3, 2);
// false
}
{
std::map<int, std::map<int, int>> my_map;
my_map[3] = { { 2, 1} };
bool result = contains_keys_cpp_17(my_map, 3, 2);
// true
}
{
std::map<char, std::map<char, char>> my_map;
my_map['3'] = { { '2', '1'} };
bool result = contains_keys_cpp_17(my_map, '3', '2');
// true
}
return 0;
}

How to create an unordered_map with a range of numbers as keys | C++

int n;
unordered_map<int,int> map(1,n);
This gives me error. I want to initialize the map with keys ranging from 1 to n. How can I do that?
I want to initialize the map with keys ranging from 1 to 5
This would make the keys [1, 5] map to the value 0:
std::unordered_map<int,int> map{
{1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}
};
If you need many keys, initializing the map with all of them may be too cumbersome and it that case you'll have to use some sort of loop.
Example:
for(int i = 1; i < 1000; ++i) map[i] = 0;
If you want to hide the fact that a loop of some sort will be used, you can use the constructor of the unordered_map that takes iterators and supply a pair of counting iterators. I think you'll find what you need in boost or you could write a special iterator for this purpose yourself:
#include <cstdint>
#include <iterator>
#include <utility>
template<class T, class U>
struct keygen {
using iterator_category = std::forward_iterator_tag;
using value_type = std::pair<T,U>;
using pointer = value_type*;
using referece = value_type&;
using difference_type = std::intmax_t;
keygen& operator++() { ++key; return *this; }
keygen operator++(int) { auto copy=*this; ++key; return copy; }
bool operator==(const keygen& rhs) const { return key == rhs.key; }
bool operator!=(const keygen& rhs) const { return key != rhs.key; }
std::pair<T,U> operator*() const { return {key, value}; }
T key;
U value;
};
int main() {
// map initialized with keys 1-1000 that maps to 0:
std::unordered_map<int,int> map(keygen<int,int>{1,0}, keygen<int,int>{1001,0});
}
You can use std::generate_n like this:
int main()
{
std::unordered_map<int, int> um;
std::generate_n(std::inserter(um, std::begin(um)), 5, [i = 1]()mutable{
return std::make_pair(std::exchange(i, i + 1), 0);
});
for(auto& p: um)
std::cout << p.first << ": " << p.second << '\n';
}
Output:
5: 0
4: 0
3: 0
2: 0
1: 0

Transforming std::map into ordered std::vector

I have a std::map that stores a string and a class and i want to make an ordered vector based on the value of a class attribute. However, when i iterate over the vector, nothing prints. My code so far is this and the compiler sees no errors:
void Championship::orderTeams(std::vector<std::pair<std::string, class Team> > vect, std::map<std::string, class Team>& map) {
for (auto const& entry : map)
{
if (vect.empty()) { //check if vector is empty and add the first pair
vect.push_back(std::make_pair(entry.first, entry.second));
continue;
}
for (auto pos = vect.begin(); pos != vect.end(); ++pos) {
if(entry.second.points > pos->second.points){
vect.insert(pos, std::make_pair(entry.first, entry.second));
}else if (pos==vect.end()){
//vect.insert(pos, std::make_pair(entry.first, entry.second)); //wanted to check if there's a differance between insert and push_back
vect.push_back(std::make_pair(entry.first, entry.second));
}
}
}
}
Class Team only contains 3 public int values( points, goalsTaken and goalsGiven), constructor and distructor.
The vector of pairs is called teamOrdered and i printed using:
for (const auto & team : teamOrdered){
std::cout<<team.first<<" "<<team.second.points<<" "<<team.second.goalsScored<<" "<<team.second.goalsTaken<<std::endl;
}
There's a few issues in your code. Firstly, the reason why you get no output at all, is because the vector is passed in by value; therefore, any changes to vect inside the function are lost. You want to pass it in by reference instead. You can also pass the map in by const reference, since you don't need to change the map.
On top of that, your sort method doesn't actually work. Consider the inner for-loop's condition, pos != vect.end(); however, you have an else if which is pos == vect.end(), which is simply impossible. Further, even after the element is added, you keep attempting to add it to vect, with a potentially invalid iterator (inserting into a vector may cause iterator invalidity).
Here's a working example of you code:
void Championship::orderTeams(std::vector<std::pair<std::string, Team>> &vect, const std::map<std::string, Team>& map) {
for (auto const& entry : map)
{
if (vect.empty()) { //check if vector is empty and add the first pair
vect.push_back(std::make_pair(entry.first, entry.second));
continue;
}
bool added = false;
for (auto pos = vect.begin(); pos != vect.end(); ++pos) {
if(entry.second.points > pos->second.points){
vect.insert(pos, std::make_pair(entry.first, entry.second));
added = true;
break;
}
}
if (!added){
vect.push_back(std::make_pair(entry.first, entry.second));
}
}
}
This can also be simplified, using std::sort from the algorithm header, and instead of taking in a vector, you can return one instead.
std::vector<std::pair<std::string, Team>> orderTeams2( const std::map<std::string, Team>& map) {
std::vector<std::pair<std::string, Team>> vect = { map.begin(), map.end() };
std::sort( vect.begin(), vect.end(), []( auto &left, auto &right ) {
return left.second.points > right.second.points;
});
return vect;
}
As pointed by other people, nothing prints for you because you passed vector by value. Pass it by reference or return the vector.
Also, you can sort using std::sort and a predicate. Here's a working solution:
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
class Team {
public:
int points;
int goalsTaken;
int goalsGiven;
};
void orderTeams(std::vector<std::pair<std::string, class Team> >& vect, std::map<std::string, class Team>& map) {
for(auto currentIterator = map.begin(); currentIterator != map.end(); ++currentIterator) {
vect.emplace_back(currentIterator->first, currentIterator->second);
}
std::sort(vect.begin(), vect.end(),
[](const std::pair<std::string, class Team>& item1, const std::pair<std::string, class Team>& item2) -> bool { return item1.second.points > item2.second.points; });
}
int main()
{
std::vector< std::pair<std::string, class Team>> teamOrdered;
std::map<std::string, class Team> map;
map.emplace(std::string("4"), Team{ 4, 4, 4 });
map.emplace(std::string("2"), Team{ 2, 2, 2});
map.emplace(std::string("1"), Team{ 1, 1, 1 });
map.emplace(std::string("3"), Team{ 3, 3, 3});
orderTeams(teamOrdered, map);
for(const auto& team : teamOrdered) {
std::cout << team.first << " " << team.second.points << " " << team.second.goalsGiven << " " << team.second.goalsTaken << std::endl;
}
}

How do I convert values from a vector to a map in c++?

I want to do something like this. Is there a stl algorithm that does this easily?
for each(auto aValue in aVector)
{
aMap[aValue] = 1;
}
If you have a vector of pairs, where the first item in the pair will be the key for the map, and the second item will be the value associated with that key, you can just copy the data to the map with an insert iterator:
std::vector<std::pair<std::string, int> > values {
{"Jerry", 1},
{ "Jim", 2},
{ "Bill", 3} };
std::map<std::string, int> mapped_values;
std::copy(values.begin(), values.end(),
std::inserter(mapped_values, mapped_values.begin()));
or, you could initialize the map from the vector:
std::map<std::string, int> m2((values.begin()), values.end());
Maybe like this:
std::vector<T> v; // populate this
std::map<T, int> m;
for (auto const & x : v) { m[x] = 1; }
You might std::transform the std::vector into a std::map
std::vector<std::string> v{"I", "want", "to", "do", "something", "like", "this"};
std::map<std::string, int> m;
std::transform(v.begin(), v.end(), std::inserter(m, m.end()),
[](const std::string &s) { return std::make_pair(s, 1); });
This creates std::pairs from the vector's elements, which in turn are inserted into the map.
Or, as suggested by #BenFulton, zipping two vectors into a map
std::vector<std::string> k{"I", "want", "to", "do", "something", "like", "this"};
std::vector<int> v{1, 2, 3, 4, 5, 6, 7};
std::map<std::string, int> m;
auto zip = [](const std::string &s, int i) { return std::make_pair(s, i); };
std::transform(k.begin(), k.end(), v.begin(), std::inserter(m, m.end()), zip);
Assuming items in vector are related in order, maybe this example can help :
#include <map>
#include <vector>
#include <string>
#include <iostream>
std::map<std::string, std::string> convert_to_map(const std::vector<std::string>& vec)
{
std::map<std::string, std::string> mp;
std::pair<std::string, std::string> par;
for(unsigned int i=0; i<vec.size(); i++)
{
if(i == 0 || i%2 == 0)
{
par.first = vec.at(i);
par.second = std::string();
if(i == (vec.size()-1))
{
mp.insert(par);
}
}
else
{
par.second = vec.at(i);
mp.insert(par);
}
}
return mp;
}
int main(int argc, char** argv)
{
std::vector<std::string> vec;
vec.push_back("customer_id");
vec.push_back("1");
vec.push_back("shop_id");
vec.push_back("2");
vec.push_back("state_id");
vec.push_back("3");
vec.push_back("city_id");
// convert vector to map
std::map<std::string, std::string> mp = convert_to_map(vec);
// print content:
for (auto it = mp.cbegin(); it != mp.cend(); ++it)
std::cout << " [" << (*it).first << ':' << (*it).second << ']';
std::cout << std::endl;
return 0;
}
A very generic approach to this, since you didn't specify any types, can be done as follows:
template<class Iterator, class KeySelectorFunc,
class Value = std::decay_t<decltype(*std::declval<Iterator>())>,
class Key = std::decay_t<decltype(std::declval<KeySelectorFunc>()(std::declval<Value>()))>>
std::map<Key, Value> toMap(Iterator begin, Iterator end, KeySelectorFunc selector) {
std::map<Key, Value> map;
std::transform(begin, end, std::inserter(map, map.end()), [selector](const Value& value) mutable {
return std::make_pair(selector(value), value);
});
return map;
}
Usage:
struct TestStruct {
int id;
std::string s;
};
std::vector<TestStruct> testStruct = {
TestStruct{1, "Hello"},
TestStruct{2, "Hello"},
TestStruct{3, "Hello"}
};
std::map<int, TestStruct> map = toMap(testStruct.begin(), testStruct.end(),
[](const TestStruct& t) {
return t.id;
}
);
for (const auto& pair : map) {
std::cout << pair.first << ' ' << pair.second.id << ' ' << pair.second.s << '\n';
}
// yields:
// 1 1 Hello
// 2 2 Hello
// 3 3 Hello
The parameter selector function is used to select what to use for the key in the std::map.
Try this:
for (auto it = vector.begin(); it != vector.end(); it++) {
aMap[aLabel] = it;
//Change aLabel here if you need to
//Or you could aMap[it] = 1 depending on what you really want.
}
I assume this is what you are trying to do.
If you want to update the value of aLabel, you could change it in the loop. Also, I look back at the original question, and it was unclear what they wanted so I added another version.
Yet another way:
#include <map>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
int main() {
using T = double;
std::vector<T> v;
auto f = [](T value) { return std::make_pair(value, 1); };
std::map<T, int> m(boost::make_transform_iterator(v.begin(), f),
boost::make_transform_iterator(v.end(), f));
}
But I don't think it beats range-for loop here in terms of readability and execution speed.
For converting values of a array or a vector directly to map we can do like.
map<int, int> mp;
for (int i = 0; i < m; i++)
mp[a[i]]++;
where a[i] is that array we have with us.