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

У меня есть строковый массив, заполненный словами из предложения.

слова[0] = "the"
слова[1] = "собака"
слова[2] = "прыгнул"
слова[3] = "over"
слова[4] = "the"
слова[5] = "стены."
слова[6] = "the"
слова[7] = "кот"
слова[8] = "упали"
слова[9] = "от"
слова[10] = "the"
слова[10] = "дом."
так далее. (Тупой пример, но он работает для этого)

каждое слово будет ключом с его следуя слову, как его значение. Итак, "over" = > "the". Некоторые ключи могут иметь несколько значений. Например, "the" = > "dog" || "wall" || "cat" / / "house". Значение выбирается случайным образом из значений для этого ключа.

когда программа запускается, она выбирает слово наугад и делает предложение. Так что это может быть что-то вроде: "кошка упала с собаки".

Я попытался реализовать карту (map myMap;), но это позволяет только одно значение на ключ (я думаю).

надеюсь, я объяснил это право.

8 ответов


вы можете использовать multimap из STL и использовать вызов

pair<iterator, iterator> equal_range(const key_type& k)

чтобы получить диапазон итераторов, которые соответствуют вашему ключ

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


std::multimap

ссылка дает отличный пример. Цитируется ниже:

 int main()
{
  multimap<const char*, int, ltstr> m;

  m.insert(pair<const char* const, int>("a", 1));
  m.insert(pair<const char* const, int>("c", 2));
  m.insert(pair<const char* const, int>("b", 3));
  m.insert(pair<const char* const, int>("b", 4));
  m.insert(pair<const char* const, int>("a", 5));
  m.insert(pair<const char* const, int>("b", 6));

  cout << "Number of elements with key a: " << m.count("a") << endl;
  cout << "Number of elements with key b: " << m.count("b") << endl;
  cout << "Number of elements with key c: " << m.count("c") << endl;

  cout << "Elements in m: " << endl;
  for (multimap<const char*, int, ltstr>::iterator it = m.begin();
       it != m.end();
       ++it)
   cout << "  [" << (*it).first << ", " << (*it).second << "]" << endl;
}

Если вы используете C++ , просто создайте класс для представления пар ключ-значение:

Class foo {
    key : String
    values : list of values
}

затем создайте карту, которая сопоставляет каждый ключ с объектом, содержащим его значения.

Это просто, extendable, и может быть сделано в любом OO-языке.

извините, мой C++ ржавый, поэтому синтаксис неправильный, но основная идея проста.


вы хотите multimap.


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

struct car_parts {

    string wheelType;
    string engine;
    int number_of_cylinders;

    car_parts(string _wheelType, string _engine, int _number_of_cylinders)
    {
        wheelType = _wheelType;
        engine = _engine;
        number_of_cylinders = _number_of_cylinders;
    }
};

int main()
{
    // Populate the dictionary
    map<char, car_parts> vehicles =
    {
        { 'I', car_parts("All terrain", "X2", 6) },
        { 'C', car_parts("Summer only", "BB", 8) },
        { 'U', car_parts("All terrain", "X3", 4) }
    };

    map<char, car_parts>::iterator it;

    it = vehicles.find('I');

    if (it != vehicles.end())
    {
        cout << "The vehicle with key of I has " << it->second.number_of_cylinders << " cylinders\n";
    }
}

как указали два других, std:: multimap может быть вашим решением.

также считают std::tr1:: unordered_multimap. Он доступен в VS 2008, похоже, имеет его, GCC имеет его, по крайней мере, с версии 4.3.


вы также можете использовать unordered_map>, который имеет некоторое преимущество над структурой карте. Вы можете сделать такую вставку, если ваш словарь похож на "c": "cat"," c":" car", "a": apple, "a": "angus":

unordered_map<char, vector<string>> char_to_strings_map;
//loop to traverse the dictionary : key:c, value:s
  char_to_strings_map[c].emplace_back(s);
//loop ends

может быть альтернативный подход для достижения двух значений на ключ, особенно для случаев, когда большинство элементов карты имеют два значения на ключ. Путем сопряжения двух значений для ключа, как указано в этом ссылке:

std::map<std::string, std::pair<std::int, int> > myMap2

использовать его в функции как:

#include<iostream>
#include<map>
#include<iterator>
using namespace std;
int main(){
map<string,pair<int,int>>mp;
mp.insert(pair<string,pair<int,int>>("ab",make_pair(50,7)));
mp.insert(pair<string,pair<int,int>>("cd",make_pair(51,8)));
map<string,pair<int,int>>::iterator it;
for(it=mp.begin();it!=mp.end();it++)
    cout<<it->first<<" "<<it->second.first<<" "<<it->second.second<<" ";
return 0;
}