Проблемы с созданием векторной функции из существующего кода C ++ - PullRequest
2 голосов
/ 05 ноября 2019

У меня есть программа, которая имеет два вектора имен и возрастов. Он сортирует вектор имен и сохраняет вектор возраста в правильном порядке, чтобы соответствовать отсортированному вектору имен. Теперь я хочу сделать функцию из существующего кода, но у меня есть некоторые проблемы.

Существующий код:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>

using namespace std;

int main() {
    vector<string> names      {"One", "Two", "Three", "Four", "Five"};
    vector<unsigned int> ages {    1,     2,       3,      4,      5};
    const vector<string> namesCopy = names;

    sort(begin(names), end(names));

    decltype(ages) sortedAges(ages.size());

    for(int i = 0; i < namesCopy.size(); ++i) {
        const auto iter = lower_bound(begin(names), end(names), namesCopy[i]);

        const auto pos = iter - begin(names);

        sortedAges[pos] = ages[i];
    }

    for(int i = 0 ; i < names.size() ; ++i)
        cout << setw(10) << names[i] << setw(4) << sortedAges[i] << '\n' ;
}

Вывод

Функция:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>

using namespace std;

int test(vector<string> testNames, vector<string> testNamesCopy, vector<unsigned int> testAges, vector<unsigned int> testSortedAges) {
    for(int i = 0; i < testNamesCopy.size(); ++i) {
        const auto iter = lower_bound(begin(testNames), end(testNames), testNamesCopy[i]);

        const auto pos = iter - begin(testNames);
        return testSortedAges[pos] = testAges[i];
    }
}

int main() {
    vector<string> names      {"One", "Two", "Three", "Four", "Five"};
    vector<unsigned int> ages {    1,     2,       3,      4,      5};
    const auto namesCopy = names;

    sort(begin(names), end(names));

    decltype(ages) sortedAges(ages.size());

    for(int i = 0 ; i < names.size() ; ++i)
        cout << setw(10) << names[i] << setw(4) << test(names, namesCopy, ages, sortedAges) << '\n' ;
}

Выход 2

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019

Я думаю, что вы подходите к этому неправильно. Наличие 2 векторов, которые вы сортируете, но должны хранить в одном и том же порядке, подвержено ошибкам. Вместо этого вы должны использовать вектор пары.

std::vector<std::pair<std::string, int>> idendityVec;

Затем вы можете отсортировать по имени (первый элемент пары), выполнив

std::sort(idendityVec.begin(), idendityVec.end());

Если вы хотите отсортировать по возрасту, вы можете объявить свою собственную функцию сравнения и использовать ее в виде: bool lesserAge(const pair<std::string,int> &a, const pair<std::string,int> &b) { return (a.second < b.second); } std::sort(idendityVec.begin(), idendityVec.end(), lesserAge); , который дает вам что-то вроде этого:

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>

bool lesserAge(const std::pair<std::string, int> &a,
               const std::pair<std::string, int> &b)
{
  return (a.second < b.second);
}
int main()
{
  std::vector<std::pair<std::string, int>> idendityVec = {std::make_pair("three", 3), std::make_pair("four", 4), std::make_pair("two", 2), std::make_pair("one", 1)};

  for (auto v : idendityVec)
  {
    std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
  }
  // Sort by age i.e. second element
  std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
  for (auto v : idendityVec)
  {
    std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
  }
  //Sort by name i.e first element
  std::sort(idendityVec.begin(), idendityVec.end());
  for (auto v : idendityVec)
  {
    std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
  }
}
0 голосов
/ 06 ноября 2019
vector<string> names      {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages {    1,     2,       3,      4,      5};

names и ages кажутся связанными таким образом, что было бы лучше сгруппировать их вместе в классе. Мы можем использовать простой struct, который по умолчанию дает вам прямой доступ к его членам, точно так же, как у вас есть доступ ко всем именам и возрастам в вашем текущем решении. Вы можете начать с этого:

struct person { // ... or animal, or thing. Give it a meaningful name.
    std::string name{};
    unsigned age{};
};

Теперь вы можете создать std::vector<person> вместо двух несвязанных векторов, что делает сортировку и общую обработку данных немного хлопотными.

С учетом вышеизложенного сортировка, печать и т. Д. Становятся более понятными. Я использовал lambdas для создания функций сортировки в примере:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <tuple> // std::tie
#include <iomanip>

struct person {
    std::string name{};
    unsigned age{};
};

// print one "person"
std::ostream& operator<<(std::ostream& os, const person& p) {
    return os << std::setw(10) << p.name << std::setw(4) << p.age;
}

int main() {
    // one vector with all the persons
    std::vector<person> persons{
        {"One", 1},
        {"Two", 2},
        {"Three", 3},
        {"Four", 4},
        {"Five", 5}
    };

    // sort on name first, age second (if names are equal) - ascending order
    std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
        return std::tie(a.name, a.age) < std::tie(b.name, b.age);
    });
    // print the current order:
    for(const auto& p : persons) std::cout << p << "\n";

    std::cout << "--\n";

    // sort on age first, name second (if ages are equal) - ascending order
    std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
        return std::tie(a.age, a.name) < std::tie(b.age, b.name);
    });
    // print the current order:
    for(const auto& p : persons) std::cout << p << "\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...