2012-01-27 4 views
2

Il y a 2 vecteurs non triés de int v1 et v2, où v1 contient un sous-ensemble de v2C++, std :: transformer remplacer les éléments par indices

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

Est-il possible, comment remplacer les éléments de v1 par indices de ses positions dans v2?

v1: 8 7 1 3 

Il n'y a aucun problème pour écrire un tel algorithme en utilisant 2 pour les cycles ...

Mais est-il une solution à l'aide en utilisant std :: transformer?

Répondre

5

Combine std::transform avec un objet fonction qui appelle 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; 
} 

La sortie:

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

@ Jared Hoberock: Merci, pourrais-je demander la soulution sans expressions lambda? Je n'ai aucune expérience avec eux ... – justik

+0

@justik: C'est juste une manière C++ 11 de créer un objet fonction. Il suffit donc de faire un type avec cette fonction comme son 'operator()'. Un objet qui prend une référence à un 'std :: Vector ' en tant que paramètre constructeur et membre de classe. –

+0

@justik: J'ai mis à jour l'exemple pour fournir une solution C++ 03 qui omet la fonction lambda. –

0

Vous pouvez utiliser std::find() dans la transformation:

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

std::transform prend un unaire -fonction-li ke-objet. Vous pouvez donc créer une classe de foncteurs qui effectue cette opération de manière efficace, en la construisant avec le deuxième vecteur, puis en appliquant ce foncteur au premier vecteur. En mettant en cache toute la deuxième liste dans une carte, trouver l'index est efficace, au lieu de nécessiter une recherche linéaire. Cela nécessite que le type T soit triable (et donc mappable). Si T n'est pas triable, une approche moins efficace nécessitant une recherche de force brute est requise.

Questions connexes