Home > Net >  Sorting a map by values - keys
Sorting a map by values - keys

Time:05-29

I'm writing a code that counts the number of occurrences of each word in a file, and print out these words in order of number of occurrences. After each word, it prints its number of occurrences. Words occurring the same number of times in the file are listed in alphabetical order.

I don't know how to modify that code to get the words in order of number of occurrences, and that words occurring the same number of times in the file are listed in alphabetical order.

Limitations: I can use only headers like <iostream>, <map>, <string>, <fstream> and <utility>

Example of how it should work:

In:

one two three one two four two one two

Out:

four 1
three 1
one 3
two 4

By now, I've done something like that:

#include <iostream>
#include <fstream>
#include <map>
#include <string>
typedef std::map<std::string, int> StringIntMap;

void count_words(std::istream &in, StringIntMap &words)
{
    std::string text;
    while (in >> text)
    {
          words[text];
    }
}

int main(int argc, char **argv)
{
    std::ifstream in("readme.txt");
    StringIntMap words_map;
    count_words(in, words_map);

    for (StringIntMap::iterator it = words_map.begin(); it != words_map.end();   it)
    {
        std::cout << it->first << " " << it->second << std::endl;
    }
}

CodePudding user response:

A solution using std::map to perform the sorting. Readability may be further improved by replacing std::pair<string, int> with a struct with a meaningful name.

#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>

using std::cout;
using std::ifstream;
using std::map;
using std::pair;
using std::string;

struct Dummy {};

struct Compare {
  bool operator()(const pair<string, int> &p1,
                  const pair<string, int> &p2) const {
    if (p1.second < p2.second) {
      return true;
    } else if (p1.second > p2.second) {
      return false;
    } else {
      return p1.first < p2.first;
    }
  }
};

int main(int argc, char **argv) {
  ifstream in("readme.txt");

  map<string, int> occurences;
  string word;
  while (in >> word) {
    occurences[word]  ;
  }

  map<pair<string, int>, Dummy, Compare> sorted;
  for (const auto &p : occurences) {
    sorted.insert({p, Dummy{}});
  }
  for (const auto &p : sorted) {
    cout << p.first.first << ": " << p.first.second << "\n";
  }
}

CodePudding user response:

you can use std::multimap to do the the sort.

int main()
{
    std::map<std::string,int> words_map;
    count_words(std::cin, words_map);
    
    std::multimap<int,std::string> frequency_map;

    for(auto& [word,freq]:words_map){
        frequency_map.insert({freq,word});
    }

    for(auto& [freq,word]:frequency_map){
        std::cout << word << ' ' << freq << '\n';
    }
}

https://godbolt.org/z/Er7o8Wec1

  •  Tags:  
  • c
  • Related