C++,std::transform-用索引替换项

C++, std::transform replace items by indices

本文关键字:索引 替换 transform- std C++      更新时间:2023-10-16

int v1和v2有两个未排序的向量,其中v1包含v2 的子集

v1: 8 12 4 17
v2: 6 4 14 17 9 0 5 12 8 

有没有办法,如何用v1在v2中的位置索引来替换v1的项目?

v1: 8 7 1 3

对于循环使用2来编写这样的算法是没有问题的。。。

但是有没有使用std::transform的解决方案?

std::transform与调用std::find:的函数对象组合

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
struct find_functor
{
  std::vector<int> &haystack;
  find_functor(std::vector<int> &haystack)
    : haystack(haystack)
  {}
  int operator()(int needle)
  {
    return std::find(haystack.begin(), haystack.end(), needle) - haystack.begin();
  }
};
int main()
{
  std::vector<int> v1 = {8, 12,  4, 17};
  std::vector<int> v2 = {6,  4, 14, 17, 9, 0, 5, 12, 8};
  // in c++11:
  std::transform(v1.begin(), v1.end(), v1.begin(), [&v2](int x){
    return std::find(v2.begin(), v2.end(), x) - v2.begin();
  });
  // in c++03:
  std::transform(v1.begin(), v1.end(), v1.begin(), find_functor(v2));
  std::cout << "v1: ";
  std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;
  return 0;
}

输出:

$ g++ -std=c++0x test.cpp
$ ./a.out 
v1: 8 7 1 3 

您可以在转换中使用std::find()

std::transform(v1.begin(), v1.end(), v1.begin(), [&](int v)->int {
    return std::find(v2.begin(), v2.end(), v) - v2.begin());
});

std::transform采用一元函数类对象。因此,您可以创建一个有效执行此操作的函子类,用第二个向量构造它,然后将该函子应用于第一个向量。

template <typename T>
class IndexSeeker{
    private:
        map<T, int> indexes;
    public:
        IndexSeeker(vector<T> source){
            for(int k = 0; k < t.size(); ++k){
                indexes[source[k]] = k;
            }
        }
        int operator()(const T& locateme){
            if(indexes.find(T) != indexes.end()){
                return indexes[T];
            }
            return -1;
        }
}

通过将整个第二个列表缓存到映射中,查找索引是高效的,而不需要线性搜索。这需要类型T是可排序的(因此是可映射的)。如果T不可排序,则需要一种效率较低的方法,需要强力搜索。