简体   繁体   中英

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::pair s 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);

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.

Edit: 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 he wanted so I added another version.

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;
}

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM