Как извлечь все ключи (или значения) из std :: map и поместить их в вектор?
Это один из возможных способов:
struct RetrieveKey { template typename T::first_type operator()(T keyValuePair) const { return keyValuePair.first; } }; map m; vector keys; // Retrieve all keys transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey()); // Dump all keys copy(keys.begin(), keys.end(), ostream_iterator(cout, "\n"));
Конечно, мы также можем извлечь все значения из карты, определив еще один функтор RetrieveValues .
Есть ли другой способ добиться этого легко? (Мне всегда интересно, почему std :: map не включает в себя функцию-член для нас.)
- Преобразование списка кортежей в словарь
- Как получить содержимое словаря Викисловаря?
- Многоязычный словарь в c #?
- SortedList , SortedDictionary и словарь
- Как использовать диапазон для цикла () с std :: map?
- Pandas groupby.size vs series.value_counts vs collections.Counter с несколькими сериями
- Пересечение java.util.Map
- Словарь VBA (Excel) на Mac?
- Как я могу получить список значений из dict?
- Итерация через словарь в Swift
- Как преобразовать class в словарь ?
- Сортировка словаря по ключу в VBA
- В чем разница между объектами HashMap и Map в Java?
Хотя ваше решение должно работать, его может быть трудно читать в зависимости от уровня навыков ваших коллег-программистов. Кроме того, он перемещает функциональность в стороне от сайта вызова. Что может сделать обслуживание немного сложнее.
Я не уверен, что ваша цель состоит в том, чтобы получить ключи в вектор или распечатать их до cout, поэтому я делаю то и другое. Вы можете попробовать что-то вроде этого:
map m; vector v; for(map::iterator it = m.begin(); it != m.end(); ++it) { v.push_back(it->first); cout << it->first << "\n"; }
Или даже проще, если вы используете Boost:
map m; pair me; // what a map is made of vector v; BOOST_FOREACH(me, m) { v.push_back(me.first); cout << me.first << "\n"; }
Лично мне нравится версия BOOST_FOREACH, потому что набирается меньше текста, и она очень ясна в том, что она делает.
//c++0x too std::map mapints; std::vector vints; vints.reserve(mapints.size()); for(auto const& imap: mapints) vints.push_back(imap.first);
Для этой цели имеется адаптер диапазона ускорения :
vector keys; // Retrieve all keys boost::copy(m | boost::adaptors::map_keys, std::back_inserter(keys));
Существует аналогичный адаптер диапазона map_values для извлечения значений.
C ++ 0x дал нам еще одно превосходное решение:
std::vector keys; std::transform( m_Inputs.begin(), m_Inputs.end(), std::back_inserter(keys), [](const std::map::value_type &pair){return pair.first;});
SGI STL имеет расширение, называемое select1st
. Жаль, что это не стандартный STL!
Я думаю, что представленный выше BOOST_FOREACH хорош и чист, однако есть и другой вариант, использующий BOOST.
#include #include std::map m; std::vector keys; using namespace boost::lambda; transform( m.begin(), m.end(), back_inserter(keys), bind( &std::map::value_type::first, _1 ) ); copy( keys.begin(), keys.end(), std::ostream_iterator (std::cout, "\n") );
Лично я не думаю, что этот подход так же чист, как подход BOOST_FOREACH в этом случае, но boost :: lambda может быть действительно чистым в других случаях.
@ Ответ DanDan, использующий C ++ 11:
using namespace std; vector keys; transform(begin(map_in), end(map_in), back_inserter(keys), [](decltype(map_in)::value_type const& pair) { return pair.first; });
и используя C ++ 14 (как отмечено @ ivan.ukr), мы можем заменить decltype(map_in)::value_type
на auto
.
Ваше решение в порядке, но вы можете использовать iterator для этого:
std::map m; m.insert(std::pair(3, 4)); m.insert(std::pair(5, 6)); for(std::map::const_iterator it = m.begin(); it != m.end(); it++) { int key = it->first; int value = it->second; //Do something }
Кроме того, если у вас есть Boost, используйте transform_iterator, чтобы избежать временной копии ключей.
Вы можете использовать универсальный boost :: transform_iterator. Преобразователь transform_iterator позволяет вам преобразовывать итерированные значения, например, в нашем случае, когда вы хотите иметь дело только с ключами, а не с значениями. См. http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example
Лучшим решением non-sgi, non-boost STL является расширение map :: iterator:
template class key_iterator : public map_type::iterator { public: typedef typename map_type::iterator map_iterator; typedef typename map_iterator::value_type::first_type key_type; key_iterator(const map_iterator& other) : map_type::iterator(other) {} ; key_type& operator *() { return map_type::iterator::operator*().first; } }; // helpers to create iterators easier: template key_iterator key_begin(map_type& m) { return key_iterator (m.begin()); } template key_iterator key_end(map_type& m) { return key_iterator (m.end()); }
и затем используйте их так:
map test; test["one"] = 1; test["two"] = 2; vector keys; // // method one // key_iterator
Бит c ++ 11:
std::map items; std::vector itemKeys; for (auto & kvp : items) { itemKeys.emplace_back(kvp.first); std::cout << kvp.first << std::endl; }
Вот хороший шаблон функции с использованием C ++ 11 magic, работающий как для std :: map, std :: unordered_map:
template class MAP, class KEY, class VALUE> std::vector keys(const MAP& map) { std::vector result; result.reserve(map.size()); for(const auto& it : map){ result.emplace_back(it.first); } return result; }
Посмотрите здесь: http://ideone.com/lYBzpL
(Мне всегда интересно, почему std :: map не включает в себя функцию-член для нас.)
Потому что он не может сделать это лучше, чем вы можете это сделать. Если реализация метода не будет превосходить реализацию свободной функции, тогда вообще вы не должны писать метод; вы должны написать бесплатную функцию.
Также не сразу понятно, почему это так полезно.