2013-09-29 2 views
0

je dois appliquer une Trouver fonctionnalité sur des éléments vectoriels (similaire à la commande Matlab TROUVER) retourner tous ocurrences. Tout en étant incapable de trouver cela en utilisant les fonctions STL avec itérateurs, je concocte cette fonction:Trouver sur un vecteur Unsorted <int>

vector<int> find(vector<int> v, int value,vector<int>*ive) 
{ 
    //Generic Find 
    vector<int> ve; 
    for (int i=0;i<v.size();i++) 
    { 
     if (v[i]==value) 
     { 
      ive->push_back(i); 
      ve.push_back(v[i]); 
     } 
    } 
return ve; 
} 

appelé avec:

//Values 
vector<int> v1 = {1,3,3,4,5,2,3,4,6,7,7,8,1,2,2,3,2,2,3,2}; 
vector<int> iRange,vRange; 
int val=2; 

//Manual FIND 
vRange=find(v1,val,&iRange); 
PrintArray(vRange); 
PrintArray(iRange); 

De retour le résultat correct:

vRange: 2 2 2 2 2 2 
iRange: 5 13 14 16 17 19 

qui bien sûr, n'utilisez pas l'objet , le sort() et * equal_range() * fonction, ce qui serait l'idéal:

pair<vector<int>::iterator,vector<int>::iterator> Range; 
sort(v1.begin(),v1.end()); 
Range=equal_range(v1.begin(),v1.end(),val); 

De retour le absolument propre, mais jusqu'à présent totalement inutile résultat, si l'on veut le résultat sur l'original, vecteur non triés:

Range Iters: 2 2 2 2 2 2 
Range:  2 3 4 5 6 7 

Comment devrais-je utiliser STL pour cela?

Merci, HYP

+1

Vous souhaitez conserver l'original 'std :: vector ' dans son ordre d'origine, mais retourner une sous-gamme représentant uniquement un choix d'objets? Cela ne marchera pas! Vous pouvez réorganiser le vecteur d'origine et renvoyer les itérateurs dans la sous-gamme sélectionnée ou vous aurez besoin d'une copie de la sous-gamme. Vous ne pouvez pas avoir les deux. –

+0

Oui !. Mais j'étais incapable de faire la fonction de passer les itérateurs hors de la fonction. Faire une fonction FIND semble être un peu 'complexe' ..... – hyprfrcb

+0

Ajout d'une dimension au vecteur pour garder l'ordre serait une solution, mais je ne sais pas comment le _sort_ fonctionne avec ça ... – hyprfrcb

Répondre

1

Si je comprends votre problème (et qui est un grand "si"), je pense cela va faire ce que vous cherchez:

#include <iostream> 
#include <iterator> 
#include <vector> 
#include <type_traits> 
#include <cstdlib> 
using namespace std; 

template<typename Iterator> 
std::vector<std::pair<Iterator, typename std::iterator_traits<Iterator>::difference_type>> find_range 
(
    Iterator begin, 
    Iterator end, 
    const typename std::iterator_traits<Iterator>::value_type& val 
) 
{ 
    std::vector<std::pair<Iterator, typename std::iterator_traits<Iterator>::difference_type>> res; 
    for (Iterator it = std::find(begin, end, val); 
     it != end; it = std::find(std::next(it), end, val)) 
     res.push_back(std::make_pair(it, std::distance(begin, it))); 
    return res; 
}; 

int main() 
{ 
    vector<int> v1 = {1,3,3,4,5,2,3,4,6,7,7,8,1,2,2,3,2,2,3,2}; 

    auto res = find_range(v1.cbegin(), v1.cend(), 2); 
    for (auto obj : res) 
     std::cout << *obj.first << ':' << obj.second << std::endl; 

    return EXIT_SUCCESS; 
} 

sortie

2:5 
2:13 
2:14 
2:16 
2:17 
2:19 

Chaque élément du vecteur résultant est une paire contenant l'itérateur dans lequel la valeur a été trouvée, et une valeur compatible de type différence qui correspond à la distance de l'itérateur débutant. Cela devrait fonctionner avec n'importe quel conteneur de séquence fournissant un forward-itérateur valide (const ou autre).

Bien sûr, vous pouvez faire la même chose en retournant simplement un std::vector<> avec des offsets et faire le calcul via std::advance, mais cela pourrait coûter cher. Vous avez déjà franchi la ligne une fois déjà. Pas besoin de le refaire (et encore ...).

Espérons que c'est ce que vous cherchiez.

+0

Un grand merci !. Honnêtement, je ne comprends pas votre code. Mais ça fonctionne bien. Il contient toutes les choses que je veux actuellement faire, donc je vais essayer de l'étendre à une version matricielle de celui-ci. Rendez-vous – hyprfrcb

+1

Désolé je n'ai pas assis sur cette réponse après l'avoir posté. Je vais essayer de prendre le temps d'écrire la description, étape par étape, de ce qu'elle fait. Les API de la bibliothèque standard sont cependant assez simples. Vous savez évidemment ce que 'std :: find()' fait. 'std :: next (it)' renvoie simplement l'itérateur * suivant * 'it'. 'std :: distance()' est simplement une magnitude (compteur) de "items" entre deux itérateurs. Tout ce que fait vraiment est de trouver l'occurrence suivante de la valeur-param, puis fait une paire de l'itérateur résultant et la distance de cet itérateur de 'begin'. – WhozCraig

Questions connexes