Maison >développement back-end >C++ >Comment puis-je créer un itérateur d'aplatissement en C pour simplifier l'itération sur les conteneurs imbriqués ?

Comment puis-je créer un itérateur d'aplatissement en C pour simplifier l'itération sur les conteneurs imbriqués ?

Patricia Arquette
Patricia Arquetteoriginal
2024-11-27 19:22:09254parcourir

How Can I Create a Flattening Iterator in C   to Simplify Iteration Over Nested Containers?

Itérateurs d'aplatissement en C

Les itérateurs conventionnels naviguent à travers les éléments d'un seul conteneur, mais nous rencontrons parfois des conteneurs imbriqués, où chaque élément du conteneur externe représente un conteneur distinct collection. Pour parcourir tous les éléments séquentiellement, nous avons besoin d'un mécanisme pour « aplatir » la structure imbriquée.

C'est là que les itérateurs d'aplatissement entrent en jeu. Ils combinent de manière transparente plusieurs niveaux de conteneurs, les présentant comme une seule séquence cohérente. On peut parcourir les éléments aplatis à l'aide d'une boucle standard basée sur une plage, comme s'ils étaient tous contenus dans un conteneur singulier.

Implémentation

Bien qu'il n'y ait pas d'implémentation intégrée dans principales bibliothèques C, un exemple d'implémentation peut être conçu :

#include <iterator>

template <typename OuterIterator>
class flattening_iterator {
public:
    using outer_iterator = OuterIterator;
    using inner_iterator = typename OuterIterator::value_type::iterator;

    using iterator_category = std::forward_iterator_tag;
    using value_type = typename inner_iterator::value_type;

    flattening_iterator() {}
    flattening_iterator(outer_iterator it) : outer_it_(it), outer_end_(it) {}
    flattening_iterator(outer_iterator it, outer_iterator end)
        : outer_it_(it), outer_end_(end) {
        if (outer_it_ == outer_end_) return;
        inner_it_ = outer_it_->begin();
        advance_past_empty_inner_containers();
    }

    reference operator*() const { return *inner_it_; }
    pointer operator->() const { return &*inner_it_; }

    flattening_iterator& operator++() {
        ++inner_it_;
        if (inner_it_ == outer_it_->end()) advance_past_empty_inner_containers();
        return *this;
    }

    flattening_iterator operator++(int) {
        flattening_iterator it(*this);
        ++*this;
        return it;
    }

    friend bool operator==(const flattening_iterator& a, const flattening_iterator& b) {
        if (a.outer_it_ != b.outer_it_) return false;
        if (a.outer_it_ != a.outer_end_ && b.outer_it_ != b.outer_end_ &&
            a.inner_it_ != b.inner_it_)
            return false;
        return true;
    }

    friend bool operator!=(const flattening_iterator& a, const flattening_iterator& b) {
        return !(a == b);
    }

private:
    void advance_past_empty_inner_containers() {
        while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end()) {
            ++outer_it_;
            if (outer_it_ != outer_end_) inner_it_ = outer_it_->begin();
        }
    }

    outer_iterator outer_it_;
    outer_iterator outer_end_;
    inner_iterator inner_it_;
};

Pour utiliser cet itérateur d'aplatissement, nous pouvons exploiter la fonction aplatir modèle :

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator it) {
    return flattening_iterator<Iterator>(it, it);
}

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator first, Iterator last) {
    return flattening_iterator<Iterator>(first, last);
}

Exemple d'utilisation

Considérez ce conteneur imbriqué :

std::unordered_set<std::vector<int>> s;
s.insert(std::vector<int>());
s.insert({ 1, 2, 3, 4, 5 });
s.insert({ 6, 7, 8 });
s.insert({ 9, 10, 11, 12 });

En utilisant l'itérateur d'aplatissement, nous pouvons parcourir de manière transparente tous les nombres :

for (auto it(flatten(s.begin(), s.end())); it != s.end(); ++it) {
    std::cout << *it << endl;  // prints 1, 2, 3, ..., 12
}

Conclusion

Les itérateurs d'aplatissement fournissent un méthode efficace et élégante pour parcourir les conteneurs imbriqués de manière linéaire. Cette approche élimine le besoin de boucles imbriquées complexes ou de gestion manuelle des index. Bien qu'elle ne fasse pas partie de la bibliothèque standard, cette implémentation peut être facilement intégrée à votre base de code pour améliorer la flexibilité et la lisibilité.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn