每个学生在不同的科目中获得满分(满分10分)。以下是带有学生名,主题,标记的示例csv文件。
我们如何使用适当的数据结构编写高效的程序来解析此文件,对其进行处理并生成输出?我们的输出应该打印出得分(和主题)得分最低的人。
john, maths, 8
roy, science, 6
john, science, 5
sara, arts, 7
neil, maths, 4
tony, arts, 6
bob, science, 7
tony, maths, 7
neil, science, 8
john, arts, 4
sara, history, 3
我们的输出应打印谁得分最低的主题(与该主题的所有其他主题相比)。所以我们的输出应该是:
neil
john
由于尼尔在数学上的得分最低,约翰在科学和艺术上的得分最低。 (但是,sara不会出现在输出中,因为sara在历史上的得分没有低于该主题的任何人)
我做了什么?
我尝试以这种方式使用两个地图:<subject, <name, marks>>
即
std::unordered_map<std::string, std::unordered_map<std::string, int>> name_subject_marks;
在这里,我将针对每个主题添加<name, marks>
。而且,如果该主题已经存在,则仅当现有分数更高时,我才替换关联的<name, marks>
。因此,最后我将获得该主题分数最低的名称。
但是,sara也出现在此列表中。我该如何处理?另外,请告诉我是否有更好的方法。
答案 0 :(得分:1)
使用布尔标志标记每个主题的第一人称。遍历每行。分割线。将标记和带有标记的名称存储在地图中。遍历地图以在集合中插入所有名称。遍历集合以打印名称。
#include <iostream>
#include <unordered_map>
#include <set>
#include <sstream>
int main() {
std::string filename;
std::cin >> filename;
std::ifstream file(filename);
std::unordered_map<std::string, std::tuple<unsigned short, std::string, bool>> lowestMarks;
std::string line;
while (std::getline(file, line)) {
std::stringstream sline(line);
std::string name;
std::string subject;
unsigned short mark;
std::getline(sline, name, ',');
std::getline(sline, subject, ' ');
std::getline(sline, subject, ',');
sline >> mark;
auto lowestMark = lowestMarks.find(subject);
if (lowestMark == lowestMarks.end()) {
lowestMarks[subject] = std::make_tuple(mark, name, true);
} else if (std::get<0>(lowestMark->second) > mark) {
lowestMarks[subject] = std::make_tuple(mark, name, false);
} else {
std::get<2>(lowestMarks[subject]) = false;
}
}
std::set<std::string> names;
for (auto lm : lowestMarks) {
if (std::get<2>(lm.second)) continue;
names.insert(std::get<1>(lm.second));
}
for (auto name : names) {
std::cout << name << '\n';
}
return 0;
}
该代码已使用clang ++ -std=c++11
进行了测试。输出是
john
neil