【问题标题】:Optimizing filtering of a vector in C++ 98在 C++ 98 中优化向量的过滤
【发布时间】:2018-05-10 14:47:29
【问题描述】:

我被分配了以下任务:创建一个包含男性、女性和未知姓名的文本文件。尝试实现一个过滤器,将这些姓名与真实姓名进行比较(因此总共输入 3 个文件:男性、女性,假设是租房者)。过滤时将匹配的名称放入相应的容器中。在我看来,这很简单,所以我按照我在下面提供的方式进行了操作。

我的问题是:有没有办法优化这段代码?

我尝试使用抽象类并基于抽象实体创建 4 个不同的对象(男人、女人、已知、未知)。但是对于这样一个简单的任务,代码量仍然很大。另一个想法是使用 lambda 表达式,但我仅限于 C++ 98。

我觉得我想多了……

#include <fstream>
#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::ifstream men("resources/men_names.txt");
    std::ifstream women("resources/women_names.txt");
    std::ifstream renters("resources/renter_names.txt");

    std::vector<std::string> menNames;
    std::vector<std::string> womenNames;
    std::vector<std::string> renterNames;
    std::vector<std::string> knownRenters;
    std::vector<std::string> unknownRenters;

    std::string name;

    while (men >> name)
        menNames.push_back(name);

    men.close();

    while (women >> name)
        womenNames.push_back(name);

    women.close();

    while (renters >> name)
        renterNames.push_back(name);

    renters.close();

    std::vector<std::string>::iterator itMen;
    std::vector<std::string>::iterator itWomen;
    std::vector<std::string>::iterator itRenters;

    for (itRenters = renterNames.begin(); itRenters != renterNames.end(); itRenters++)
    {
        bool found = false;

        for (itMen = menNames.begin(); itMen != menNames.end(); itMen++)
        {
            if ((*itMen) == (*itRenters))
            {
                found = true;
                knownRenters.push_back((*itMen));
            }
        }
        if (!found)
        {
            for (itWomen = womenNames.begin(); itWomen != womenNames.end(); itWomen++)
            {   
                if ((*itWomen) == (*itRenters))
                {
                    found = true;
                    knownRenters.push_back((*itWomen));
                }
            }   
        }
        if (!found)
            unknownRenters.push_back((*itRenters));
    }

    std::cout << knownRenters.size() << '\n';
    std::cout << unknownRenters.size() << '\n';

    std::cin.get();

    return 0;
}

【问题讨论】:

  • "但我仅限于 C++ 98。" - 这样的老师不应该已经退休了吗?
  • "有没有办法优化这段代码?"优化是指减少代码量,还是让代码运行得更快?
  • 为什么需要为女性和男性使用不同的容器?您为什么要搜索 vector 而不是 set?你为什么要将租用者读入一个集合然后循环遍历它?
  • codereview.stackexchange.com 可能更适合这个问题。
  • 编写一个函数来读取名称文件并返回这些名称的排序向量。用它来阅读男人和女人。获得这两个向量后,只需一次从租户那里读取一个名称,然后检查它是否在两个向量中的任何一个中。您无需在搜索前存储所有租用者姓名。

标签: c++ file vector filter c++98


【解决方案1】:

现有代码的缩短。这应该都是 C++98

#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <iterator>

int main()
{
    std::ifstream men("resources/men_names.txt");
    std::ifstream women("resources/women_names.txt");
    std::set<std::string> peopleNames;

    peopleNames.insert(std::istream_iterator<std::string>(men), std::istream_iterator<std::string>());
    peopleNames.insert(std::istream_iterator<std::string>(women), std::istream_iterator<std::string>());

    std::ifstream renters("resources/renter_names.txt");
    std::vector<std::string> knownRenters;
    std::vector<std::string> unknownRenters;

    for (std::string name; renters >> name; )
    {
        if (peopleNames.count(name))
            knownRenters.push_back(name);
        else
            unknownRenters.push_back(name);
    }

    std::cout << knownRenters.size() << '\n';
    std::cout << unknownRenters.size() << '\n';

    std::cin.get();

    return 0;
}

【讨论】:

  • 2 OP - 如果您不能使用 std::set 将其替换为 std::vector,请在插入之后或插入期间对其进行排序,然后使用 std::binary_search
  • 我明白了!谢谢!
【解决方案2】:

你不关心租客是男是女,只要他们有一个公认的名字。所以,不要存储两个已知名称的平面向量,存储所有已识别名称的单个 std::set&lt;std::string&gt;(或排序向量,或 std::unordered_set,如果您曾被允许使用 C++11)。

然后,您可以进行一次对数时间查找(或 C++11 版本的恒定时间),而不是(最多)对每个租户进行两次线性搜索。

您似乎也不关心被识别(或未被识别)的租户的姓名,所以不要保留两个结果向量:只需增加一个 knownunknown 计数器。

【讨论】:

  • 是的,现在我明白了。我仅限于 C++ 98,但是 std::set 工作得很好。还在学习...谢谢!
猜你喜欢
  • 2016-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 2019-01-03
相关资源
最近更新 更多