Оптимизация фильтрации вектора в C ++ 98 - PullRequest
0 голосов
/ 10 мая 2018

Мне было дано следующее задание: создать текстовый файл, содержащий мужчин, женщин и неизвестные имена. Попробуйте реализовать фильтр, который будет сравнивать эти имена с реальными именами (итого 3 входных файла: мужчины, женщины и, скажем, арендаторы). При фильтрации поместите совпадающие имена в соответствующие контейнеры. Это показалось мне довольно прямым, поэтому я сделал это так, как я представляю внизу.

Мой вопрос: Есть ли способ, как оптимизировать этот код?

Я пытался использовать абстрактные классы и создавать 4 различных объекта (Мужчина, Женщина, Известный, Неизвестный) на основе абстрактной сущности. Но объем кода был все еще велик для такой простой задачи. Другая идея заключалась в том, чтобы использовать лямбда-выражения, но я ограничен только 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;
}

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Тебе все равно, арендатор мужчина или женщина, просто если у него есть узнаваемое имя. Поэтому не храните два плоских вектора известных имен, сохраняйте один std::set<std::string> всех распознанных имен (или отсортированный вектор, или std::unordered_set, если вам когда-либо разрешено использовать C ++ 11).

Затем вместо двух (не более) двух линейных поисков для каждого арендатора вы можете выполнить один поиск в логарифмическом времени (или в постоянном времени для версии C ++ 11).

Кажется, вам также не важны имена арендаторов, которые были распознаны (или нет), поэтому не оставляйте два вектора результатов: просто увеличьте счетчик known или unknown.

0 голосов
/ 10 мая 2018

Сокращение вашего существующего кода. Это должно быть все 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;
}
...