2009-11-27 9 views
6

Поскольку в C++ std: map нет функции .resize(). Мне было интересно, как можно получить std :: map с максимум n элементами ,Как получить первые n элементов std :: map

Очевидным решением является создание цикла от 0 до n и использование n-го итератора в качестве первого параметра для std :: erase().

Мне было интересно, есть ли какое-либо решение, которое не нуждается в цикле (по крайней мере, не в моем пользовательском коде) и является более «STL-способом».

+1

Хм .. Я бы сказал, что использование цикла итератора * - это способ STL, не так ли? – schnaader

+2

Нет 'std :: erase'. Используйте 'std :: map :: erase()' –

ответ

13

Для этого вы можете использовать std::advance(iter, numberofsteps).

+0

+1 - не знал, что - хороший. – schnaader

0

Почему вы хотите изменить размер карты?

Элементы карты не сохраняются в любом порядке - первый «п» на самом деле не значит ничего

редактировать:
Интересно станд :: Карта имеет порядок, не знаю, как полезно эта концепция.
Являются ли записи в том же порядке сортировки, что и ключи?
Что это значит? Если у вас есть Имена, введенные с помощью SSN, это означает, что имена хранятся в цифровом порядке SSN?

+0

Не упорядочены ли элементы по ключу? –

+0

Не так, как вы думаете, элементы в некотором порядке в памяти. Существует алгоритм хеширования, который преобразует ключ в индекс. Но элементы для key1 и key2 не обязательно находятся рядом друг с другом. –

+3

@mgb Нет, это будет хэш-таблица. Std :: map - это двоичное дерево поиска (обычно это красно-черное дерево, которое должно быть конкретным). Поэтому элементы в std :: map сохраняются таким образом, что они делают итерацию в порядке просто и быстро. – Tim

1

STD :: map - это не список. Нет «первых n» элементов.

КПП: Итераторы становятся недействительными, если контейнер изменен.

Если вам действительно нужна меньшая карта, вы могли бы ее перебрать и добавить все элементы до n-й в новую карту.

+3

Ну, элементы сортируются по их ключу, не так ли? – Nailer

+0

@Nailer: Ницца, я этого не знал. Эта ссылка подтверждает: http://www.cplusplus.com/reference/stl/map/ – ya23

+1

Да, они есть. Но карта «скорее всего реализуется как (сбалансированное) дерево узлов» (цитата «Язык программирования C++», Bjarne Stroustrup), а не список. Поэтому mymap [n] не имеет никакого смысла. – EricSchaefer

3

Универсальное решение для почти любого контейнера, такого как std :: list, std :: map, boost :: multi_index. Вы должны проверить только размер своей карты.

template<class It> 
It myadvance(It it, size_t n) { 
    std::advance(it, n); 
    return it; 
} 

template<class Cont> 
void resize_container(Cont & cont, size_t n) { 
    cont.erase(myadvance(cont.begin(), std::min(n, cont.size())), 
       cont.end()); 
} 
+0

это void std :: advance(), поэтому это не скомпилировалось. – Norbert

+0

Справа. Я исправил. –

+0

+1, но если вы убираете это для выпуска, вам придется решить, на чем работает концепция 'resize_container'. Имена параметров и параметров шаблона предлагают любой контейнер. Имя параметра функции предлагает любую карту. Как написано, я думаю, что он действительно будет работать над любой последовательностью или ассоциативным контейнером, что, к сожалению, означает, что его домен является полифилетической группой в таксономии C++. –

1

Правильный способ для этого - использовать std :: advance. Но вот забавный (медленный) способ, позволяющий «использовать изменение размера на карте». В более общем плане такой трюк можно использовать для других вещей, работающих над вектором, но не на карте.

map<K,V> m; //your map 
vector< pair<K,V> > v(m.begin(), m.end()); 
v.resize(n); 
m = map<K,V>(v.begin(),v.end()); 
Смежные вопросы