Page 1 of 1

std::multimap

PostPosted: Tue Oct 17, 2017 4:22 am
by Lena
Hi.
I would like to have a container multimap would store the key multiple values, such as:
key=String
int value1
int value2
Code: Select all
std::multimap<String, std::vector<int> > IniContent;
//***
String FullName = item->Data[L"FullName"].AsString();
std::vector<int> &values = IniContent[FullName]; //error here
//***

[bccaarm Error] UnitDibocca.cpp(59): type 'std::multimap<String, std::vector<int> >' does not provide a subscript operator
How correct?
C++ Builder Berlin.

Re: std::multimap

PostPosted: Tue Oct 17, 2017 5:12 am
by Lena
And an additional question
If I do not need automatic sorting (in multimap), which container should I use?
Code: Select all
std::vector<std::pair<String, std::pair<int,int>> > MyPair;
//***
String FullName = item->Data[L"FullName"].AsString();
std::vector<std::pair<int,int>> &values = MyPair[FullName];//error
//***

[bccaarm Error] UnitDibocca.cpp(64): no viable overloaded operator[] for type 'std::vector<std::pair<String, std::pair<int, int> > >'

Re: std::multimap

PostPosted: Tue Oct 17, 2017 6:07 pm
by rlebeau
Lena wrote:[bccaarm Error] UnitDibocca.cpp(59): type 'std::multimap<String, std::vector<int> >' does not provide a subscript operator


The error is correct. std::multimap does not have a subscript operator.

Lena wrote:How correct?


You should be using std::map instead:

Code: Select all
std::map<String, std::vector<int>> IniContent;


std::multimap allows multiple entries to have the same key value, which is why a subscript operator is not provided (you have to use std::multimap::equal_range() to find all entries that match a given key value). That is not what you want. std::map holds entries with unique keys, and thus provides a subscript operator to access entries by key value.

Also, on a side note, since you are using a C++11 compiler, you should consider using 'auto' to help clean up your variable declarations when the compiler can deduce their types for you:

Code: Select all
std::map<String, std::vector<int>> IniContent;
...
auto &values = IniContent[FullName]; // <-- here


Lena wrote:If I do not need automatic sorting (in multimap), which container should I use?


Have a look at std::unordered_map:

Code: Select all
std::unordered_map<String, std::vector<int>> IniContent;


Lena wrote:
Code: Select all
std::vector<std::pair<String, std::pair<int,int>> > MyPair;
//***
String FullName = item->Data[L"FullName"].AsString();
std::vector<std::pair<int,int>> &values = MyPair[FullName];//error
//***

[bccaarm Error] UnitDibocca.cpp(64): no viable overloaded operator[] for type 'std::vector<std::pair<String, std::pair<int, int> > >'


Correct, because the subscript operator of std::vector takes an array index, not a key value. If you want to use a vector of pairs, you will have to use the std::find_if() algorithm to find a given pair by its key value:

Code: Select all
using MyPair = std::pair<String, std::vector<int>>;
std::vector<MyPair> IniContent;
...
String FullName = item->Data[L"FullName"].AsString();
auto iter = std::find_if(IniContent.begin(), IniContent.end(),
                         [=](const MyPair &pair){ return (pair.first == FullName); });
if (iter == IniContent.end())
{
    IniContent.emplace_back(FullName, std::vector<int>());
    iter = IniContent.end() - 1;
}
auto &values = iter->second;
// use values as needed...

Re: std::multimap

PostPosted: Wed Oct 18, 2017 3:28 am
by Lena
Thank you very much for the detailed explanation!

For example I need a container allows multiple entries to have the same key value and not need automatic sorting.
Is the simplest way use std::find_if() ?
and definition
Code: Select all
using MyPair = std::pair<String, std::vector<int>>;
std::vector<MyPair> IniContent;
//***

Re: std::multimap

PostPosted: Wed Oct 18, 2017 10:12 am
by rlebeau
Lena wrote:For example I need a container allows multiple entries to have the same key value and not need automatic sorting.


Why, though? You are keying off of a person's name. Are you expecting multiple users to have the same name? When searching for a name, how do you expect to differentiate between different people of the same name? If you just search for the name by itself, you will always find one and only one person, but you won't know if it is the right person, especially in an unordered container where ANY user may be the first one found.

What are you REALLY trying to accomplish?

Re: std::multimap

PostPosted: Wed Oct 18, 2017 11:39 am
by Lena
What are you REALLY trying to accomplish?


This menu is for a restaurant. For example, two identical names for a salad. In one of the salads there is salt, but not in the other. Salad names can be the same.

Re: std::multimap

PostPosted: Wed Oct 18, 2017 2:28 pm
by rlebeau
Lena wrote:This menu is for a restaurant. For example, two identical names for a salad. In one of the salads there is salt, but not in the other. Salad names can be the same.


Doesn't it make more sense to name them differently instead? For instance, "Salad - Salted" and "Salad - Unsalted", or "Salad w/ Salt" and "Salad w/o Salt". If you give them the exact same name, and you key off of the names, you are just making things harder for yourself. Personally, I would not identify items by name to begin with. It makes more sense to track the items by unique ID numbers instead, then you can give multiple items different IDs but the same name for display purposes.

Re: std::multimap

PostPosted: Thu Oct 19, 2017 5:39 am
by Lena
You are absolutely right. According to your recommendations, I convinced the owner of the restaurant that all dishes should have a different name. Thank you for your recommendations. Your recommendations convinced the owner of the restaurant!
Your support is the best! Thank You for this forum!