簡體   English   中英

使用stl置換std :: vector元素的最短解決方案

[英]Shortest solution to permute the elements of a std::vector using stl

假設您有一個類型Tstd::vector<T>和該std::vector<int>的索引std::vector<int>的選擇。 現在,我正在尋找一個函數permute(const std::vector<T>& vector, const std::vector<int>& indices) ,該permute(const std::vector<T>& vector, const std::vector<int>& indices)返回相對於給定索引的置換向量。

通過編寫如下所示的簡短函數可以輕松解決該問題:

template<typename T>
std::vector<T> permute(const std::vector<T>& matrix, const std::vector<int>& indices) {
    std::vector<T> ret;
    for (auto p : indices) {
        ret.push_back(matrix[p]);
    }
    return ret;
}

int main(int, char**) {
    std::vector<int> perm{ 1,2,0 };
    std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
    auto matrixPerm=permute(matrix, perm);
    std::cout << matrixPerm[0][0] << " == " << matrix[1][0] << std::endl;
    std::cout << matrixPerm[1][0] << " == " << matrix[2][0] << std::endl;
    std::cout << matrixPerm[2][0] << " == " << matrix[0][0] << std::endl;
}

我現在想知道如果可以使用STL甚至Boost庫,那么該程序最優雅的版本是什么。 例如,在STL中,我們有shuffle() ,但是我們不能說以什么方式洗牌。

現在有人,如何縮短功能?

使用std::transform()解決方案

#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

int main(int, char**) {
    std::vector<int> perm{ 1,2,0 };
    std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
    std::vector<std::vector<double>> output;
    std::transform(perm.begin(), perm.end(), std::back_inserter(output), [&](int i) { return matrix[i]; });

    std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
    std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
    std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}

您可以將索引轉換為迭代器,然后使用Boost.Range創建一個間接范圍。

#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>

int main(int, char**) {
    using namespace boost::adaptors;


    std::vector<int> perm{ 1,2,0 };
    std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
    std::vector<std::vector<double>> output;
    auto permutation = perm | transformed( [&matrix](int x) { return matrix.begin() + x; }) | indirected;

    boost::copy(
        permutation,
        std::back_inserter(output));

    std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
    std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
    std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}

如果不需要實向量,可以跳過復制元素並僅處理范圍的方法。

范圍適配器使用Boost.Iterator庫中的置換迭代器。 您也可以直接使用它,但是必須手動定義開始和結束:

auto begin = make_permutation_iterator( matrix.begin(), perm.begin() );
auto end = make_permutation_iterator( matrix.end(), perm.end() );

std::copy(begin, end, std::back_inserter(output) );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM