C++ 我需要一个具有多个值的键。你会推荐什么数据结构?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/698345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:49:18  来源:igfitidea点击:

I need to have a key with multiple values. What datastructure would you recommend?

c++data-structureskey

提问by irl_irl

I have an string array filled with words from a sentence.

我有一个字符串数组,里面装满了一个句子中的单词。

words[0] = "the"
words[1] = "dog"
words[2] = "jumped"
words[3] = "over"
words[4] = "the"
words[5] = "wall."
words[6] = "the"
words[7] = "cat"
words[8] = "fell"
words[9] = "off"
words[10] = "the"
words[10] = "house."

etc. (Stupid example, but it works for this)

等(愚蠢的例子,但它适用于此)

Each word will be a key with it's following word as it's value. so "over" => "the". Some keys can have multiple values. For example, "the" => "dog" || "wall" || "cat" || "house". The value is randomly chosen from those for that key.

每个单词都将是一个键,它的下一个单词作为它的值。所以“结束”=>“那个”。一些键可以有多个值。例如,"the" => "dog" || “墙” || “猫”|| “房子”。该值是从该键的值中随机选择的。

When the program runs it picks a word at random and makes a sentence. So it could be something like: "the cat fell off the dog".

当程序运行时,它会随机选择一个单词并造一个句子。所以它可能是这样的:“猫从狗身上掉下来了”。

I tried implementing a map (map myMap;) but this allows only one value per key (I think).

我尝试实现一个地图 (map myMap;) 但这只允许每个键一个值(我认为)。

Hope I explained this right.

希望我解释正确。

采纳答案by irl_irl

you can use a multimap from the STL and use the call

您可以使用 STL 中的 multimap 并使用调用

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

to get a range of iterators that match your key

获取一系列与您的键匹配的迭代器

personally i find this slightly clunky due to having to deal with iterator ranges rather than just getting an object back that represents all values for that key. to get around that you could also store a vector in a regular map and add your strings to the vector.

我个人觉得这有点笨拙,因为必须处理迭代器范围,而不仅仅是取回一个代表该键所有值的对象。为了解决这个问题,您还可以在常规地图中存储一个向量并将您的字符串添加到该向量中。

回答by dirkgently

std::multimap

std::multimap

The link provides an excellent example. Quoted below:

该链接提供了一个很好的例子。引用如下:

 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;
}

回答by Larry Watanabe

If you're using C++ then just create a class to represent your key-value pairs:

如果您使用的是 C++,那么只需创建一个类来表示您的键值对:

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

Then, create a map that maps each key to an object containing its values.

然后,创建一个映射,将每个键映射到包含其值的对象。

This is simple, extendable, and can be done in any OO-language.

这很简单,可扩展,并且可以用任何 OO 语言完成。

Sorry, my C++ is rusty so the syntax is wrong, but the essential idea is straightforward.

抱歉,我的 C++ 生疏了,所以语法是错误的,但基本思想很简单。

回答by demibrahim

You may also use unordered_map<char,vector<string>>which has some benefit over map structure. You can do such insertion if your dictionary is like 'c': "cat", 'c':"car", 'a':apple, 'a':"angus":

您也可以使用unordered_map<char,vector<string>>which 比地图结构有一些好处。如果您的字典类似于'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

回答by S. Arseneau

I've found that a struct may work well for this situation. This approach (basically akin to a class) allows a cleaner access to your parameters named as you see fit.

我发现结构可能适用于这种情况。这种方法(基本上类似于类)允许更清晰地访问您认为合适的命名参数。

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";
    }
}

回答by Manuel

As two others pointed out, std::multimapcan be your solution.

正如其他两个人指出的那样,std::multimap可以成为您的解决方案。

Also consider std::tr1::unordered_multimap. It is available in VS 2008seems to have it, GCChas it at least from version 4.3.

还要考虑std::tr1::unordered_multimap。它VS 2008似乎可以使用,GCC至少从 version 开始可以使用4.3

回答by warriorUSP

There can be an alternate approach to achieve two values per key, especially for the cases when most of the map elements have two values per key. By pairing two values for a key, as mentioned in this link:

可以有另一种方法来实现每个键两个值,特别是对于大多数地图元素每个键有两个值的情况。通过为一个键配对两个值,如本链接所述

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

use it in the function as:

在函数中使用它作为:

#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;
}