Предположим, у нас есть два std :: vectors v1 и v2, и мы не хотим объединять их в структуру. Как преобразовать v2 так же, как v1 был преобразован сортировкой? - PullRequest
2 голосов
/ 14 марта 2020

Это продолжение этого вопроса . Единственная разница заключается в том, что два вектора не могут быть объединены в структуру.

Предположим, у нас есть вектор

std::vector<double> v1 = {9.0,5.0,3.0,2.0,1.0};

Теперь мы сортируем вектор v1. Пусть v2 будет дано

std::vector<std::string> v2 = {"you?","are","how","there","hello"};

Как преобразовать v2 так же, как v1 был преобразован с помощью сортировки?

Ответы [ 3 ]

3 голосов
/ 14 марта 2020

Исходя из этого ответа , вы можете использовать массив индексов для "сортировки" вектора значений типа double и просто использовать полученный индексный массив для индексации вектора строк.

#include <algorithm>
#include <iostream>
#include <string>
#include <numeric>

int main()
{
    std::vector<double> v1 = {5.0,9.0,3.0,2.0,1.0};
    std::vector<std::string> v2 = {"are", "you?","how","there","hello"};

    // Create an array of indices, starting from 0
    std::vector<int> index(v1.size());
    std::iota(index.begin(), index.end(), 0);

    // "Sort" the index array according to the value in the vector of doubles
    std::sort(index.begin(), index.end(), 
              [&](int n1, int n2){ return v1[n1] < v1[n2]; });

    // Output results
    for (auto i : index )
      std::cout << v2[i] << " " << v1[i] << ", index is " << i << "\n";
}

Вывод:

hello 1, index is 4
there 2, index is 3
how 3, index is 2
are 5, index is 0
you? 9, index is 1

Примечание:

Я изменил исходные данные, чтобы проиллюстрировать, как работает индексный массив.

3 голосов
/ 16 марта 2020

Абстракция, которую вы пропускаете - это возможность просматривать векторы как один элемент. Это та роль, для которой вектор индексов является прокси в другом ответе.

Я думаю, что стоит упомянуть, что есть библиотеки, которые предоставляют такую ​​концепцию (часто под названием «zip»). Например, с range-v3:

std::vector<double> v1 = {5, 9, 3, 2, 1};
std::vector<std::string> v2 = {"are", "you?", "how", "there", "hello"};

// Sort the vectors
ranges::actions::sort(ranges::views::zip(v1, v2));

// Output results
for (std::size_t i = 0; i < v1.size(); ++i)
  std::cout << v2[i] << " " << v1[i] << ", index is " << i << "\n";
0 голосов
/ 14 марта 2020

В возможном решении используется помощник std::vector<int>:

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

template<typename T>
void MySort(std::vector<T> t, std::vector<int>& helper)
{
    struct StructHelper
    {
        T t1;
        int num;
        StructHelper(T t, int i): t1{t}, num{i} {};
        bool operator<(const StructHelper& other) const
        { return t1 < other.t1; }
    };

    std::vector<StructHelper> shVector;

    for(int i=0; i<t.size(); ++i)
    {
        shVector.emplace_back(t[i], i);
    }

    std::sort(shVector.begin(), shVector.end());
    helper = std::vector<int>(t.size());

    for(int i=0; i<t.size(); ++i)
    {
        helper[i] = shVector[i].num;
    }

}

template<typename T>
void MySortUsingHelper(std::vector<T>& t1, const std::vector<int>& helper)
{
    if(t1.size() != helper.size()) throw std::out_of_range("not same size");
    std::vector<T> t2(t1.size());

    for(int i=0; i<helper.size(); ++i)
    {
        t2[i] = t1[helper[i]];
    }

    t1 = t2;
}

int main() {

    std::vector<double> v1 = {9.0,5.0,3.0,2.0,1.0};
    std::vector<int> helper;

    MySort(v1, helper);

    std::vector<std::string> v2 = {"you?","are","how","there","hello"};

    MySortUsingHelper(v2, helper);

    for(auto elem : v2)
    {
        std::cout << elem << " ";
    }

    return 0;
} 

Вы можете запустить приведенный выше код онлайн , чтобы увидеть следующий вывод:

hello there how are you? 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...