Associate strings

Hello,

i would like to know if could be possible to associate a string with multiple other strings

with this code i can associate a pair of string

 
  dictionary.insert(make_pair("Dog", "terrier"));


could be possible to associate 3 or four string?

 
  dictionary.insert(make_??("Dog", "terrier", "white", "old"));

Do you mean something like this?

1
2
3
4
5
6
7
8
9
#include <map>
#include <vector>
#include <string>

// Create the object
std::map<std::string, std::vector<std::string> > dictionary;

// Example of setting a value
dictionary["Dog"] = {"terrier", "white", "old"};


EDIT:
Here is a quick example:
http://coliru.stacked-crooked.com/a/230ae066ea57c761
Last edited on

I would like to search through the dictionary with a function

1
2
3
4
5
6
7
8
9
10
string searchDictionary(string wordToSearch) {
    // searching
    map<string, string>::iterator it = dictionary.find(wordToSearch);
    if(it != dictionary.end()) {
        //cout << "Found! " << it->first << " is " << it->second << "\n";
        return it->second ;
    }else {
        return "Not found";
    }
}


The above works with two words or a pair, but how the function could look like for more words?

Bwt, i cannot use "auto", cause i'm using c++ 0x3
Last edited on
Do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// use a typedef
typedef std::vector<std::string> dictType;

dictType searchDictionary(std::string wordToSearch) {
    std::map<std::string, dictType>::iterator it;
    it = dictionary.find(wordToSearch);

    if (it != dictionary.end()) {
        return it->second;
    } else {
        // Return empty set of results
        return dictType();
    }
}

// example usage

dictType results = searchDictionary("colour");
if (!results.empty()) {
    std::cout << "Colour: ";
    for (dictType::const_iterator it = results.begin(); it != results.end(); ++it) {
        std::cout << *it << " ";
    }
} else {
    std::cout << "No results found.";
}
Last edited on
Normally if you have more values associated to the same key, you should be using std::multimap instead of emulating it std::map + std::vector combo.

However if you want to access the elements via index, then NT3's suggestion is already spot-on.

How a function would look like if a have to search with more words?
Example search for "color" is "red", return the associated third and fourth words


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    std::map<std::string, std::vector<std::string> > dictionary;

    // C++11 initializer lists would sure come in handy
    dictionary["red"].push_back("crimson");
    dictionary["red"].push_back("scarlet");
    dictionary["red"].push_back("carmine");
    dictionary["red"].push_back("rosewood");

    if (dictionary.count("red") == 0)
        std::cerr << "Red not available!\n";
    else
        std::cout << dictionary["red"][2] << std::endl;
}

Thank you: i will try.

Just a question, the previous routine can print the first and the second elements.

it is possibile to do this way also?

cout << "Found! " << it->first << " is " << it->second << "\n" << it->third << "\n" << it->fourth;

maybe something similar
Last edited on
No, but you can do it this way:

1
2
std::cout << "Found! " << it->first << " is " << 
    it->second[0] << " " << it->second[1] << " " << it->second[2]


Though, if you do that, you have to be sure that there ARE at least 3 words associated with the key.
(it->second.size() can tell you)
Last edited on
Thank you very much.

I've got the point, now.

You could also look into tuples:
http://en.cppreference.com/w/cpp/utility/tuple
Thank you for the informations.

The example of NT3 is interesting.
Have to investigate on the Tuple too. It's a specific c++11 or is available on c++0x?
going to search about std::multimap too.
Last edited on
Use std::map< std::string, std::vector<std::string> > dictionary;

Not std::multimap< std::string, std::string > dictionary ;

Definitely not: std::map< std::string, std::tuple<std::string,std::string,std::string> > dictionary ;
@ JLBorges: since I was the one who brought up std::multimap, I'd be thankful if you gave an explanation as to why you're against it.
You should use std::multimap when you have keys that need not be unique, not when you want to associate more than one value with a single (unique) key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <map>
#include <string>

int main()
{
    std::multimap<std::string, std::string> map;
    map.emplace("Dog", "terrier");
    map.emplace("Dog", "white");
    map.emplace("Dog", "old");

    std::cout << "Keys in map: " << map.size() << '\n';

    for (auto& mapped : map)
        std::cout << mapped.first << ": " << mapped.second << '\n';
}
Keys in map: 3
Dog: terrier
Dog: white
Dog: old
Last edited on
@NT3

map<string, vector<string> > myDictionary;
myDictionary["cat"] = {"siamese", "15", "3-legged", "pussy", "George"};

This doesn't work for me:
error: 'myDictionary' does not name a type|
> I'd be thankful if you gave an explanation as to why you're against it.

I'm not against the use of std::multimap<> per se; for this particular use-case, I do not favour it.

We have been through this before:
http://www.cplusplus.com/forum/general/116621/#msg636620

This is what meant by 'clarity and simplicity':

std::map< std::string, std::vector<std::string> >:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void print( const std::map< std::string, std::vector<std::string> >& dict )
{
    for( const auto& e : dict )
    {
        std::cout << e.first <<  " => " ;
        for( const std::string& s : e.second ) std::cout << '"' << s << '"' << ' ' ;
        std::cout << '\n' ;
    }
}

std::list<std::string> look_up( const std::map< std::string, std::vector<std::string> >& dict,
                                const std::string& key )
{
    auto iter = dict.find(key) ;
    if( iter != dict.end() ) return { iter->second.begin(), iter->second.end() } ;
    else return {} ;
}

std::multimap<std::string,std::string>:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void print( const std::multimap<std::string,std::string>& dict )
{
    if( !dict.empty() )
    {
        auto beg = dict.begin() ;
        std::string prev_key = beg->first ;
        std::cout << beg->first <<  " => " ;

        for( const auto& e : dict )
        {
            if( e.first != prev_key )
            {
               prev_key = e.first ;
               std::cout << '\n' << e.first <<  " => " ;
            }
            std::cout << '"' << e.second << '"' << ' ' ;
        }
        std::cout << '\n' ;
    }
}

std::list<std::string> look_up( const std::multimap<std::string,std::string>& dict,
                                  const std::string& key )
{
    std::list<std::string> result ;

    auto pair = dict.equal_range(key) ;
    for( auto iter = pair.first ; iter != pair.second ; ++iter )
        result.push_back(iter->second) ;

    return result ;
}
Could we see your full code? And do you have any other errors/warnings? There is nothing wrong with that code snippet there in itself.
http://ideone.com/cPJ1iO
Solved:

my mistake, sorry.

I put the myDictionary initializzazion in the global declaration area :P

This warning i get
warning: control reaches end of non-void function [-Wreturn-type]|

In the example you linked me, you used the "auto" keyword

I don't use c++0x11. Auto is a specific c++011 version or what?
Last edited on
can't implement this example: could someone help me?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// use a typedef
typedef std::vector<std::string> dictType;

dictType searchDictionary(std::string wordToSearch) {
    std::map<std::string, dictType>::iterator it;
    it = dictionary.find(wordToSearch);

    if (it != dictionary.end()) {
        return it->second;
    } else {
        // Return empty set of results
        return dictType();
    }
}


1
2
3
4
5
6
7
8
9
10
// example usage
dictType results = searchDictionary("colour");
if (!results.empty()) {
    std::cout << "Colour: ";
    for (dictType::const_iterator it = results.begin(); it != results.end(); ++it) {
        std::cout << *it << " ";
    }
} else {
    std::cout << "No results found.";
}


In particular, i don't know how to insert into dictType.

While with

map<string, string> dictionary;

i can do: dictionary.insert(make_pair("Cat", "Siamese"));

i can't find the correct syntax for doing the same with the
typedef std::vector<std::string> dictType;

someone can help me?

Thank you

C++98:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <map>
#include <vector>

typedef std::vector<std::string> mapped_type ;
typedef std::map< std::string, mapped_type > dictionary_type ;

mapped_type look_up( const dictionary_type& dict, const std::string& word )
{
    dictionary_type::const_iterator iter = dict.find(word) ;
    if( iter != dict.end() ) return iter->second ;
    else return mapped_type() ;
}

int main()
{
    dictionary_type dict ;

    // insert
    dict[ "Cat" ].push_back( "Siamese") ;
    dict[ "Cat" ].push_back( "Persian") ;
    dict[ "Cat" ].push_back( "Bengal") ;
    dict[ "Cat" ].push_back( "Devon") ;
    dict[ "Cat" ].push_back( "Angora") ;

    dict[ "Dog" ].push_back( "Beagle") ;
    dict[ "Dog" ].push_back( "Pug") ;
    dict[ "Dog" ].push_back( "Dalmatian") ;

    // look_up
    std::cout << "Cat\n" ;
    mapped_type vec = look_up( dict, "Cat" ) ;
    for( std::size_t i = 0 ; i < vec.size() ; ++i )
        std::cout << "  " << vec[i] << '\n' ;
    std::cout << '\n' ;

    std::cout << "Dog\n" ;
    vec = look_up( dict, "Dog" ) ;
    for( std::size_t i = 0 ; i < vec.size() ; ++i )
        std::cout << "  " << vec[i] << '\n' ;
    std::cout << '\n' ;

    std::cout << "Rabbit\n" ;
    vec = look_up( dict, "Rabbit" ) ;
    for( std::size_t i = 0 ; i < vec.size() ; ++i )
        std::cout << "  " << vec[i] << '\n' ;
    std::cout << '\n' ;

}

http://coliru.stacked-crooked.com/a/441533fc0b0e4c7b
Topic archived. No new replies allowed.