multi map count for string key's

This website has an example of how to get a count of duplicate keys for chars when using the multimap, but how could this be implemented using strings?

any ideas??


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
// multimap::count
#include <iostream>
#include <map>

int main ()
{
  std::multimap<char,int> mymm;

  mymm.insert(std::make_pair('x',50));
  mymm.insert(std::make_pair('y',100));
  mymm.insert(std::make_pair('y',150));
  mymm.insert(std::make_pair('y',200));
  mymm.insert(std::make_pair('z',250));
  mymm.insert(std::make_pair('z',300));

  for (char c='x'; c<='z'; c++)
  {
    std::cout << "There are " << mymm.count(c) << " elements with key " << c << ":";
    std::multimap<char,int>::iterator it;
    for (it=mymm.equal_range(c).first; it!=mymm.equal_range(c).second; ++it)
      std::cout << ' ' << (*it).second;
    std::cout << '\n';
  }

  return 0;
}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <map>
#include <string>


int main ()
{
    std::multimap<std::string, int> mymm;

    mymm.emplace("Hello", 50);
    mymm.emplace("Bye",  100);
    mymm.emplace("Bye",  150);
    mymm.emplace("Bye",  200);
    mymm.emplace("?",    250);
    mymm.emplace("?",    300);

    for(auto it = mymm.cbegin(), end = mymm.cend(); it != end; it = mymm.upper_bound(it->first))
        std::cout << it->first << ' ' << mymm.count(it->first) << '\n';
}
? 2
Bye 3
Hello 1
http://coliru.stacked-crooked.com/a/03477ea0ae8a07cc
http://melpon.org/wandbox/permlink/dihbJTOQO5jh9ePo
Last edited on
whats up with the declaration a vector <int> of keys that appears to be unused?

Oops, forgot to remove it. I used it to store unique keys for later use. Ignore it.

Edit: cleaned code and made it work with C++11.
Last edited on
I will have to investigate this because this doesn't compile when I test run it...it says it does not name a type.

I see you got it to work, but it isn't working. I just opened up a new source, and ran it...no luck compiling it...

it's saying end is not defined, so I added string before it, then it said it not defined, so I'm not sure how you got it to run in this format...
What IDE do you use? It looks like you do not turn on C++11 support.

You can replace auto in loop with std::multimap<std::string, int>::const_iterator if you want, and change cbegin()/cend() to begin()/end()
I'm running testing/writing using ubuntu and g++ and sublime....It is a VM...not sure how to turn on C++11
This worked...had to get the std::literals off, and remove the s...but thanks a lot...I will play around with this and see how useful it is....also, will look up C++11 if you don't already know how to turn it on for ubuntu...



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

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

using namespace std;

int main ()
{
    std::multimap<std::string,int> mymm;

    mymm.insert(std::make_pair("Hello",50));
    mymm.insert(std::make_pair("Bye",100));
    mymm.insert(std::make_pair("Bye",150));
    mymm.insert(std::make_pair("Bye",200));
    mymm.insert(std::make_pair("?",250));
    mymm.insert(std::make_pair("?",300));


    for(std::multimap<std::string, int>::const_iterator it = mymm.begin(), end = mymm.end(); it != end; it = mymm.upper_bound(it->first)) {
        std::cout << it->first << ' ' << mymm.count(it->first) << '\n';
    }
}
pass -std=c++11 to compiler options (or you can try to pass -std=c++1y to turn on C++14)

Alternatively this will work even in C++98:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <map>
#include <string>


int main ()
{
    std::multimap<std::string,int> mymm;

    mymm.insert(std::make_pair("Hello",50));
    mymm.insert(std::make_pair("Bye",100));
    mymm.insert(std::make_pair("Bye",150));
    mymm.insert(std::make_pair("Bye",200));
    mymm.insert(std::make_pair("?",250));
    mymm.insert(std::make_pair("?",300));

    for(std::multimap<std::string, int>::const_iterator it = mymm.begin(), end = mymm.end();
        it != end; it = mymm.upper_bound(it->first))
    {
        std::cout << it->first << ' ' << mymm.count(it->first) << '\n';
    }
}
Last edited on
I'm trying to randomly access different keys in the multimap using this...but it's not right...

*-----
update

fixed it...

how can I change the location of it2->first so that it will return a random element with the keyword I send to it?

1
2
3
4
5
6
7
  

int ran = rand() % keyword_count[i];
std::advance(it2, ran);
 token2_copy[i]= (it2->second)->getString(); 

 
Last edited on
Use equal_range to get pait of iterators. And I suggest to move to C++11 random facilities as they are more powerful and random.
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
#include <iostream>
#include <map>
#include <string>
#include <ctime>
#include <cstdlib>
#include <iterator>


int main ()
{
    std::srand(std::time(nullptr));
    std::multimap<std::string, int> mymm;

    mymm.emplace("Hello", 50);
    mymm.emplace("Bye",  100);
    mymm.emplace("Bye",  150);
    mymm.emplace("Bye",  200);
    mymm.emplace("?",    250);
    mymm.emplace("?",    300);

    auto range = mymm.equal_range("Bye");
    auto count = std::distance(range.first, range.second);
    if (count != 0) {
        auto it = std::next(range.first, std::rand() % count);
        std::cout << it -> second;
    }
}
http://ideone.com/8i9H2G
you're a smart fellow...

I will give this a whirl...I am trying to build a madlib program...I tried to do it recursively, but I resorted to tokens.

I have a class that actually facilitates the randomization process because it randomly chooses a keyword associated with the keyword stored in the map.

I am not able to get my strings to become members of the class I created, so I am trying to find an alternative way to get the program to work.

Then I'll try to make it better.

I am going to get c++11, but I don't want my vm to shut down right now if something goes wrong, so I'll do it after I finish this project tonight.

If you have any ideas as to how I can store multiple inherited classes together after parsing them from a text file, I am all ears.

My method is not very effective for larger texts, only small text documents at the moment. :/
If you have any ideas as to how I can store multiple inherited classes together after parsing them from a text file, I am all ears.
You mean, you parse text and depending on context, create instances of different classes which have common base? Use container of [smart]pointers.
what do you mean [smart]pointers?
You can use raw pointers like T*, but they have drawbacks. For example you need to manually delete them or you will have a leak, you can accidentally delete it twice, you can use it after deletion...
If you will use something like std::unique_ptr<T>, most of the problems go away: it automatically delete object when pointer is not exist anymore, Absense of manual delete makes it impossible to delete twice and the fact that unique_prt exist in one instance makes it impossible to accidentally use it after destruction.
I am using pointers...but for some reason, the values aren't changing when I add them to the vector<Choice*>,

see this code I posted earlier...

http://www.cplusplus.com/forum/beginner/145996/

Choice* inherits from Exp* and is a vector that comes in between delimiters, it stores Exp*, which are terminals in my usage

Terminal* is a string that inherits from Exp*

Sequence* is a vector that stores Exp* that inherits from Exp* which are terminals and choices in my usage.

Keyword* is a string that inherits from Exp*

Exp* is the interface class
Last edited on
Can someone help me figure out how to make a key pair for parsed words in here:



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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129



Exp* parse(multimap<string, Exp*>* keywords, string input){
// Fill me in! figure out what type of expr it is in parse, do recursively
    string line_inside_parse = input;
    string new_line_after_parse_extraction;
    string expression;
    Choice* parsed_choice_expressions= new Choice();
    Sequence* parsed_sequence_expressions = new Sequence();
    vector<string> vector_of_expressions;
    
    //cout<<"line_inside_parse: "<< line_inside_parse << endl;
  
    size_t pos= input.find('|');
    if(pos != string::npos){
        
        //cout<<"line inside parse: "<< line_inside_parse << endl;
        expression =  line_inside_parse.substr(0, pos);
        Choice* ret = new Choice();


        ret->addExpression(parse(keywords, expression));
        //parsed_choice_expressions->addExpression(parse(keywords, expression));
        //parsed_choice_expressions->addExpression(ret);
        //cout<<"expression before for inside parse: " << expression << endl;
        new_line_after_parse_extraction = line_inside_parse.substr(pos + 1);
       // return parsed_terminal;
        //cout<<"new line after parse before for inside parse: " << new_line_after_parse_extraction << endl;
        //Terminal* initial_parse_to_terminal_expression = new Terminal(expression);
        //parsed_choice_expressions->addExpression(initial_parse_to_terminal_expression);
        //cout<<"parsed_choice expressions inside parse before for: " << parsed_choice_expressions->getString() << endl;
        vector_of_expressions.push_back(expression);
        //store the terminal inside the choice vector
         //cout<<"new_line_after_parse_extraction outside while loop: " << new_line_after_parse_extraction << endl;
       // cout<<"newline size outside while: " << new_line_after_parse_extraction.size() << endl;
        
    //for(int i = 0; i < new_line_after_parse_extraction.size(); i++){
        while(new_line_after_parse_extraction.size() != 0 && new_line_after_parse_extraction != expression){
          //cout<<"\ninside while\n";
                  //cout<<"newline size inside while: " << new_line_after_parse_extraction.size() << endl;
                  pos = new_line_after_parse_extraction.find('|');
                  expression = new_line_after_parse_extraction.substr(0, pos);
                  vector_of_expressions.push_back(expression);
                  //cout<<"expression inside parse inside for loop: " << expression << endl;
                  new_line_after_parse_extraction = new_line_after_parse_extraction.substr(pos + 1);
                  //cout<<"newline size inside while: " << new_line_after_parse_extraction.size() << endl;
                  //cout<<"new_line_after_parse_extraction inside while: " << new_line_after_parse_extraction << endl;
                  //cout<<"size of line after extraction: " << text_file_expressions_after_extraction.length() << endl;
                 // Terminal* parse_to_terminal_expression = new Terminal(expression);
                  
                 // parsed_choice_expressions->addExpression(parse(keywords, expression));
                  //parsed_choice_expressions->addExpression(parse_to_terminal_expression);
                  //cout<<"parsed_choice expressions inside parse inside for loop: " << parsed_choice_expressions->getString() << endl;
                  //cout<<"vector_of_expressions size: " << vector_of_expressions.size() << endl;
                  //for(int i = 0; i < vector_of_expressions.size(); i++)\\
                  //cout<<"\nhere " << endl;
                  ret->addExpression(parse(keywords, expression));
                   //cout<<"vector of expressions: " << i+1 << ": "<< vector_of_expressions[i] << endl;
                  //cout<<"ret inside while loop: " <<  ret->getString() << endl;
                  //if(new_line_after_parse_extraction == expression){
                  //return parse(keywords, new_line_after_parse_extraction);
                    //ret->addExpression(parse(keywords, expression));
                        //break;
                  //}      

        }

          if(pos == string::npos){
        //Choice* ret = new Choice();
            expression = new_line_after_parse_extraction.substr(0, pos);
            //cout<<"expression at npos: " << expression << endl;
            ret->addExpression(parse(keywords, expression));
          }    
        //cout<<"vector_of_expressions size: " << vector_of_expressions.size() << endl;
      vector<Exp*> vector_of_terminals(vector_of_expressions.size());
      for(int i = 0; i < vector_of_expressions.size(); i++){

        //vector_of_terminals.push_back(new Terminal(vector_of_expressions[i]));
        vector_of_terminals[i] = new Terminal(vector_of_expressions[i]);
        //cout<< "vector of terminals: " << i+1 <<": " << vector_of_terminals[i]->getString() << endl;
        //parsed_choice_expressions->addExpression(parse(keywords, vector_of_terminals[i]->getString()));
        parsed_choice_expressions->addExpression(vector_of_terminals[i]);
        //cout<<"parsed_choice_expressions: " << i << " : " << parsed_choice_expressions->getString() << endl;

      }
             
        //parsed_choice_expressions->addExpression(parsed_terminal);
        //parsed_sequence_expressions->addExpression(parsed_choice_expressions);
        //cout<<"parsed choice expressions inside parse: " << parsed_choice_expressions->getString() << endl;
        //cout<<"expression: " << expression << endl;
        //parse(keywords, line_inside_parse);
        //return parse(keywords, line_inside_parse);

        cout<<"ret before return: " << ret->getString() << endl;

        return ret;
    }

int main() {

 multimap<string, Exp*> keyword_map2;

multimap<string, Exp*>::iterator it4= keyword_map2.begin();

loopcount = 0;
            if(pos != string::npos){
                  keyword_in_text = text_file_line.substr(0, pos);
                  stored_keywords_vector.push_back(keyword_in_text);//keywords vector
                  cout<<"keyword: " << keyword_in_text << endl;
                  stored_lines_vector.push_back(text_file_line.substr(pos + 1));//lines vector after colon extracted

                  Keyword* text_keyword = new Keyword(&keyword_map2, keyword_in_text);

                  keyword_map2[keyword_in_text] = parse(&keyword_map2, stored_lines_vector[loop_count]);
                  keyword_map2.insert(it4, std::make_pair<string, Exp*>(parse(keyword_in_text, stored_lines_vector[loop_count]));
                  //Exp* text_file_parsed_call= parse(&keyword_map2, stored_lines_vector[loop_count]);
                  //cout<<"text file after parse called : " << text_file_parsed_call->getString() << endl;

                  //keyword_map[keyword_in_text] = parse2(&keyword_map, stored_lines_vector[loop_count]);

                 //cout<<"k: " << keyword_map2[keyword_in_text]->getString() << endl;

            }
loopcount++;

}

Topic archived. No new replies allowed.