跟踪重复键STL映射?

时间:2013-12-18 21:15:15

标签: c++ dictionary stl duplicates

我正在尝试使用STL映射编写代码,该映射从文件中读取并解析该行。如何跟踪文件中的重复项?关键值是术语和部分。我想把重复项放在一个向量中,但我不太清楚如何。还是有更好的方法吗?

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <ctime>
#include <utility>
#include <vector>
#include <map>

using namespace std;

int main()
{
  map <string, map <string, int> > subjectCourse;
  vector <string> duplicate;

  // for parsing the input file
  char* token;
  char buf[1000];
  const char* const tab = "\t";

 // open the input file
 ifstream fin;
 fin.open("schedule.txt");
 clock_t startTime = clock(); // start timer
 if (!fin.good()) throw "I/O error";

 while (fin.good())
 {
  // read line
  string line;
  getline(fin, line);
  strcpy(buf, line.c_str());
  if (buf[0] == 0) continue;

  // parse line
  const string term(token = strtok(buf, tab));
  const string section(token = strtok(0, tab));
  const string course((token = strtok(0, tab)) ? token : "");
  const string instructor((token = strtok(0, tab)) ? token : "");
  const string whenWhere( (token = strtok(0, tab)) ? token : "");
  if (course.find('-') == string::npos) continue; // invalid line
  const string subjectCode(course.begin(), course.begin() + course.find('-'));
  subjectCourse[subjectCode][course]++; // enter data to the map
}

fin.close();

for(map<string, map<string, int> >::iterator i = subjectCourse.begin(); i!= subjectCourse.end(); ++i){
cout << (*i).first << ", " << (*i).second.size() << " courses.\n";
  for(map<string, int>::iterator j = (*i).second.begin(); j != (*i).second.end(); ++j)
    cout << "   " << (*j).first << ", " << (*j).second << " class(es).\n";
}

2 个答案:

答案 0 :(得分:2)

看起来像你需要的是std::multimap

答案 1 :(得分:0)

我更喜欢multimap

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <ctime>
#include <utility>
#include <vector>
#include <map>

using namespace std;

int main()
{
  multimap <string, string> subjectCourse;
  vector <string> duplicate;

    // for parsing the input file
  char* token;
  char buf[1000];
  const char* const tab = "\t";

    // open the input file
  ifstream fin;
  fin.open("schedule.txt");
    clock_t startTime = clock(); // start timer
    if (!fin.good()) throw "I/O error";

    while (fin.good())
    {
    // read line
      string line;
      getline(fin, line);
      strcpy(buf, line.c_str());
      if (buf[0] == 0) continue;

    // parse line
      const string term(token = strtok(buf, tab));
      const string section(token = strtok(0, tab));
      const string course((token = strtok(0, tab)) ? token : "");
      const string instructor((token = strtok(0, tab)) ? token : "");
      const string whenWhere( (token = strtok(0, tab)) ? token : "");
    if (course.find('-') == string::npos) continue; // invalid line
    const string subjectCode(course.begin(), course.begin() + course.find('-'));
    subjectCourse.insert(std::make_pair(subjectCode, course)); // enter data to the map
  }

  fin.close();

  for(multimap<string, string>::iterator i = subjectCourse.begin(); i!= subjectCourse.end(); ++i)
  {
    cout << " " << i->first << " course, " << i->second << " class(es).\n";
  }
}

http://ideone.com/Zrf7RO

唯一的好处是代码简化(不再是容器的容器)。

如果您想要每门课程的课程数量:

 multimap<string, string>::iterator it = subjectCourse.begin();
 while (it != subjectCourse.end())
 {
   multimap<string, string>::iterator next_it = subjectCourse.upper_bound(it->first);
   cout << " " << it->first << " course as " << std::distance(it, next_it) << " class(es).\n";
   it = next_it;
 }

如果您想跟踪重复次数:

multimap<string, string>::iterator it = subjectCourse.begin();
while (it != subjectCourse.end())
{
  multimap<string, string>::iterator next_it = it;
  while ((subjectCourse.end() != next_it) 
         && (*it == *next_it))
  {
    ++next_it;
  }

  cout << " " << it->first << " course, " << it->second << " classes: " << std::distance(it, next_it) << " occurences.\n";
}

http://ideone.com/AqggCV