【问题标题】:Finding out lowest scoring students in each subjects, using C++/STL使用 C++/STL 找出每个科目中得分最低的学生
【发布时间】:2019-07-16 15:06:07
【问题描述】:

每个学生在不同科目上都获得了分数(满分 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

由于 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 也出现在此列表中。我该如何处理?如果有更好的方法,请告诉我。

【问题讨论】:

  • 好吧,只要排除其中只有 1 个项目的任何主题。
  • 你需要使用C++11吗?使用 C++14 transparent comparator 会更容易
  • 不应该是neil john john吗?
  • 反对票可能是因为您描述了代码而不是包含它。只发布你所拥有的

标签: c++ c++11 stl


【解决方案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

【讨论】:

  • 离题:考虑使用std::make_tuple而不是使用构造函数语法。
  • 这确实很棒。但我没有从用户那里阅读。我会将其更改为从文件中读取。我的是csv文件。非常感谢。
  • 顺便说一句,使用 std::map 而不是哈希 (unordered_map) 背后的任何原因?
  • @Fureeish 已修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
相关资源
最近更新 更多