Вопрос
Как установить все значения в std::map
к одному и тому же значению без использования цикла, перебирающего каждое значение?
Решение
В С++ есть fill
метод из <algorithm>
но это не работает для карт.На самом деле поддержка алгоритмов для ассоциативных контейнеров обычно не очень хороша.
В результате вам придется использовать взаимодействие или написать соответствующий функтор, который будет использоваться с for_each
(но я считаю это ненужными накладными расходами):
template <typename TKey, typename TValue>
struct resetter : public std::unary_function<std::pair<TKey, TValue> > {
TValue const value;
public resetter(value const& v) : value(v) { }
public void operator ()(std::pair<TKey, TValue>& v) {
v.second = value;
}
};
for_each(map.begin(), map.end(), resetter<Key, Value>(value));
Другие советы
Я столкнулся с той же проблемой, но обнаружил, что диапазон, возвращаемый boost::adaptors::values, является изменяемым, поэтому его можно использовать с обычными алгоритмами, такими как std::fill.
#include <boost/range/adaptor/map.hpp>
auto my_values = boost::adaptors::values(my_map);
std::fill(my_values.begin(), my_values.end(), 123);
В библиотеке boost::assign есть множество полезных вещей, которые помогут инициализировать содержимое контейнера.Я подумал, что это можно использовать, чтобы избежать явного повторения карты.К сожалению, карты — любопытные создания, которые сложно инициализировать, поскольку ключи должны быть уникальными.Суть в том, что простой цикл for, вероятно, является лучшим способом инициализации карты.Возможно, он не очень элегантен, но выполняет свою работу и сразу понятен любому, кто знаком с STL.
map <int,string> myMap;
for( int k=0;k<1000;k++)
myMap.insert(pair<int,string>(k,string("")));
Оставшаяся часть статьи описывает путь, который я проделал, чтобы прийти к вышеуказанному выводу.
boost::assign упрощает присвоение карте небольшого количества значений.
map<string,int> m;
insert( m )( "Bar", 1 )( "Foo", 2 );
или
map<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);
В вашем случае, когда вы хотите инициализировать всю карту одним и тем же значением, есть утилиты повторение и повтор_fun.
Что-то вроде этого должно работать с мультикартой (непроверенный фрагмент кода)
pair<int,string> init( 0,string(""));
multimap <int,string> myMap = repeat(1000,init);
Как отметил Конрад Рудольф, вы не можете инициализировать карту с тем же точным значением, поскольку ключи должны быть уникальными.
Это делает жизнь намного сложнее (веселее?).Что-то вроде этого, возможно:
map <int,string> myMap;
struct nextkey
{
int start;
nextkey( s ) : start( s ) {}
pair<int,string> operator () ()
{
return pair<int,string>(start++,string(""));
}
};
myMap = repeat_fun(1000,nextkey(0));
Теперь это становится настолько сложным, что теперь я думаю, что простая итерация — это правильный путь.
map <int,string> myMap;
for( int k=0;k<1000;k++)
myMap.insert(pair<int,string>(k,string("")));