简体   繁体   English

在C ++ 98中优化向量的过滤

[英]Optimizing filtering of a vector in C++ 98

I was given a following task: create a text file which contains men, women and unknown names. 我得到了以下任务:创建一个包含男人,女人和未知名称的文本文件。 Try to implement a filter that will compare those names with real names (so 3 files on input in total: men, women and let's say renters). 尝试实现一个过滤器,将那些名称与真实名称进行比较(因此,总共输入了3个文件:男性,女性,比如说房客)。 While filtering put matching names in their appropriate containers. 过滤时,将匹配的名称放入其适当的容器中。 It seemed to me pretty straight forward so I did it the way I provide underneath. 在我看来,这很简单,所以我按照下面提供的方式进行了操作。

My question is: Is there a way how to optimize this code? 我的问题是: 有没有一种方法可以优化此代码?

I tried to use abstract classes and create 4 different objects (Man, Woman, Known, Unknown) based on abstract entity. 我试图使用抽象类,并基于抽象实体创建4个不同的对象(男人,女人,已知,未知)。 But the amount of code was still large for such a simple task. 但是对于这样一个简单的任务,代码量仍然很大。 Another idea was to use lambda expressions, but I am limited to C++ 98 only. 另一个想法是使用lambda表达式,但是我仅限于C ++ 98。

I think I am overthinking it... 我想我想得太多了...

#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;
}

A shortening of your existing code. 缩短现有代码。 This should be all C++98 这应该都是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;
}

You don't care whether a renter is male or female, just if they have a recognised name. 您不在乎租户是男性还是女性,即使他们有公认的名字。 So, don't store two flat vectors of known names, store a single std::set<std::string> of all recognised names (or a sorted vector, or a std::unordered_set if you're ever allowed to use C++11). 因此,请勿存储两个已知名称的平面向量,而应存储所有已识别名称的单个std::set<std::string> (或排序后的向量,或者如果允许使用std::unordered_set话) C ++ 11)。

Then, instead of doing (at most) two linear searches per renter, you can do a single logarithmic-time lookup (or constant-time for the C++11 version). 然后,您可以(仅对数时间)查找(对于C ++ 11版本为常数时间),而不是(每个租户最多)进行两次线性搜索。

You also don't seem to care about the names of the renters who were recognised (or not), so don't keep two result vectors: just increment a known or unknown counter. 您似乎也不必关心被认可(或未被认可)的房客的姓名,因此不要保留两个结果向量:仅增加knownunknown计数器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM