2010-12-02 8 views
6

Quel est le meilleur moyen de filtrer tous les éléments d'une structure de données qui n'obéissent pas à un certain prédicat? c'est-à-dire une méthode similaire aux méthodes "filtre" dans les langages de programmation fonctionnels.Méthode de filtrage pour les structures de données C++

+1

duplication possible de ["filtre" fonction d'ordre supérieur en C++] (http://stackoverflow.com/questions/3635260/filter-higher-order-function-in-c) – missingfaktor

Répondre

5

Les algorithmes du langage STL sont remove_if et remove_copy_if.

+3

Et rappelez-vous que "supprimer" dans STL ne supprime rien, pousse juste les indésirables à l'arrière du bus. ** Je vous regarde, Rosa Parks! **;) Vous devez toujours appeler 'container.erase (returnIter, container.end())'. –

0

Ceci devrait fonctionner pour toutes les classes de conteneurs qui ont des itérateurs. En utilisant un pointeur pour montrer que le conteneur sera modifié en passant par la fonction.

UnaryFunction nécessite un type de retour bool. Bien que l'utilisation des fonctions appropriées STL pourrait être plus intelligent ...

template <class Container, 
      class UnaryFunction> 
void filter(Container *container, UnaryFunction func) 
{ 
    typedef typename Container::iterator iter; // g++ complains w/o typename 
    for(iter elem(container->begin()); elem != container->end();) 
     elem = (func(&*elem)) ? (elem + 1) 
           : container->erase(elem); 
} 
+1

Il serait préférable d'utiliser une référence au lieu d'un pointeur (il est plus clair que l'intention est de modifier, pas d'acquérir la propriété). De plus, cela serait assez coûteux pour les vecteurs, puisque pour chaque élément, tous les éléments de cette position sont supprimés jusqu'à la fin du vecteur, et pour les deques, la suppression du milieu est une opération coûteuse pour les mêmes raisons. Le seul conteneur séquentiel pour lequel ceci est efficace sont des listes. –

+0

@Rodriguez - Eh bien, le point que j'essayais de faire en référence était que vous ne pouvez pas ignorer que vous passez dans le tableau réel avec la déclaration 'filter (& vec, someFunc)' alors que'filter (vec, someFunc) 'pourrait induire en erreur certains qui ne prennent pas la peine de regarder la déclaration de fonction. Deuxièmement, je réalise que ce n'est pas le code le plus opportun pour les vecteurs ou les files d'attente, mais le PO a spécifiquement demandé une fonction de filtre qui fonctionne sur toutes les structures de données - c'est exactement ce que nous faisons; on peut discuter de l'efficacité. Cependant, vos points sont valides et doivent être pris en compte par le PO. – IAE

+0

Et parce qu'il utilise '(elem + 1)', il ne fonctionne que pour les conteneurs d'accès aléatoire. (Les conteneurs associatifs nécessiteraient une boucle d'effacement manuelle avec une logique différente en premier lieu.) – visitor

0

Si vous utilisez coup de pouce, vous pouvez utiliser la bibliothèque boost.iterator, qui a filter_iterator pour votre cas. Même si vous ne le faites pas, il est assez facile d'écrire le vôtre.

Questions connexes