C ++ как скопировать карту в вектор

Как лучше всего в C ++ скопировать пару с карты в вектор? Я делаю это, чтобы впоследствии отсортировать вектор.


person Jack BeNimble    schedule 26.03.2009    source источник
comment
Карты отсортированы. Вы должны указать, хотите ли вы выполнить сортировку по другому параметру или по другому ключу. В противном случае на вопрос ответьте сами: не делайте этого.   -  person David Rodríguez - dribeas    schedule 26.03.2009
comment
Закрытие как дубликат, поскольку (более новый) дубликат, по мнению некоторых, имеет гораздо более высокое качество.   -  person Drew Dormann    schedule 19.12.2018


Ответы (7)


Это должно делать то, что вы хотите:

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

bool cmp(const pair<int, int>  &p1, const pair<int, int> &p2)
{
    return p1.second < p2.second;
}

int main()
{
    map<int, int> m;
    for(int i = 0; i < 10; ++i)
        m[i] = i * -i;

    vector<pair<int, int> > v;
    copy(m.begin(), m.end(), back_inserter(v));

    sort(v.begin(), v.end(), cmp);

    for(int i = 0; i < v.size(); ++i)
        cout << v[i].first << " : " << v[i].second << endl;
    return 0;
}
person CTT    schedule 26.03.2009

Если вы используете std :: map, он уже отсортирован по ключу. Просто создайте итератор и выполните итерацию по карте от begin () до end (), и все готово.

Если вы хотите выполнить сортировку по чему-то другому, кроме ключа карты, вы можете использовать тот же итератор и помещать копию каждого элемента в свой вектор при итерации по карте.

person Spire    schedule 26.03.2009
comment
Может быть еще проще: вы можете указать компаратор в CTor карты. - person foraidt; 16.03.2010

Предполагая, что вы хотите скопировать ключ и значение:

std::map<Foo, Bar> m;


// Map gets populated 
// (...)


// Copying it to a new vector via the constructor
std::vector<std::pair<Foo, Bar>> v(m.begin(), m.end());


// Copying it to an existing vector, erasing the contents
v.assign(m.begin(), m.end());

// Copying it to the back of an existing vector
v.insert(v.end(), m.begin(), m.end());
person Andrew Shepherd    schedule 26.03.2009
comment
Последнее неверно. Может быть, вы имеете в виду v.insert (v.rbegin (). Base (), m.begin (), m.end ()); ? - person wilhelmtell; 26.03.2009
comment
whihelmtell - Как вы думаете, почему это неверно? Только что попробовал - работает нормально. - person Andrew Shepherd; 26.03.2009
comment
Подумайте об этом: v.rebegin (). Base () возвращает тот же итератор, что и v.end () - person Andrew Shepherd; 26.03.2009
comment
Все должно быть в порядке, если v.size () ›= 1. Диапазон вставляется из элемента перед итератором позиции. - person Functastic; 26.03.2009
comment
Ничего страшного, даже если вектор пуст. В этом случае v.insert (v.end (), m_begin (). M.end ()) идентичен v.insert (v.begin (), m_begin (). M.end ()), поскольку v. begin () == v.end (). - person Andrew Shepherd; 26.03.2009
comment
Думаю, я неправильно прочитал эту последнюю строчку. Игнорируйте мой комментарий выше. :) - person wilhelmtell; 27.03.2009
comment
Спасибо за оптимальные синтаксические фрагменты (например, строку v.assign). - person ; 06.04.2009

map хранит пару - ключ и значение. Какую часть вы хотите скопировать? Или вы хотите скопировать и то, и другое в два разных vector?

Я хочу скопировать оба. Как только это будет сделано, мне нужно выяснить, как отсортировать вектор по второму значению в паре.

template <class V>
struct sort_by_val {
  bool operator()(V const& l, V const& r) {
        return // ...
  }
};

vector<pair<K, V> > outv(map.begin(), map.end());

sort(outv.begin(), outv.end(), sort_by_val());
person dirkgently    schedule 26.03.2009
comment
Я хочу скопировать оба. Как только это будет сделано, мне нужно выяснить, как отсортировать вектор по второму значению в паре. - person Jack BeNimble; 26.03.2009
comment
+1, ясное и простое решение. @Jack: вам действительно стоит поместить информацию из своего комментария в основной вопрос, поскольку это очень актуально - например, это бы помешало всем упомянуть, что карты уже отсортированы по их первым элементам. - person j_random_hacker; 26.03.2009

Если ваша цель - просто отсортировать по типу, а не по ключу, вы можете посмотреть Boost :: Bimap. Это позволяет вам получить доступ к обеим частям пары карт как к ключам. Предположительно, вы могли бы перебирать его по порядку второго ключа так же легко, как и первый.

person Michael Kohne    schedule 26.03.2009

Вы можете использовать другую карту (или набор) и использовать преобразование для сортировки при вставке:

#include <map>
#include <algorithm>

typedef std::map<unsigned int, signed char> MapType1;
typedef std::map<MapType1::mapped_type, MapType1::key_type> MapType2;

struct SwapPair
{
  MapType2::value_type operator()(MapType1::value_type const & v)
  {
    return std::make_pair (v.second, v.first);
  }
};

int main ()
{
  MapType1 m1;
  for(int i = 0; i < 10; ++i)
    m1[i] = i * -i;

  MapType2 m2;
  std::transform (m1.begin ()
      , m1.end ()
      , std::inserter (m2, m2.end ())
      , SwapPair ());
}

Я забыл добавить, что если вам нужно делать это часто, может быть лучше просто использовать boost мультииндексный контейнер.

person Richard Corden    schedule 26.03.2009

person    schedule
comment
Этот кажется более элегантным и простым - person Prabhu R; 26.03.2009
comment
Да, это лучший, особенно первый. Несколько поясняющих комментариев: Если у вас есть typedef std::map<K,V> MapType, вы не можете объявить вектор vector<MapType::value_type> как value_type - это pair<const K, V>, который не имеет оператора = и не может быть скопирован в вектор. Кроме того, во втором примере очень важно сначала передать размер вектора (либо через конструктор, либо через резерв), потому что копия не будет выделять пространство в векторе по мере добавления элементов, и есть большая вероятность, что вы перейдете конец начального распределения вектора. - person Christopher Howlin; 09.12.2010
comment
copy(m.begin(), m.end(), v.begin()); дал мне ошибку сегментации. Просто говорю. - person yasith; 13.02.2012
comment
@yasith Вам нужно зарезервировать размер вектора или использовать back_inserter (). - person Deepak Mohanty; 02.09.2018
comment
@DeepakMohanty На самом деле вам нужно использовать vector :: resize () или vector :: reserve И back_inserter (). - person Virus_7; 24.05.2021