web-dev-qa-db-fra.com

C ++ étendre un vecteur avec un autre vecteur

Je suis un programmeur C/Python dans les terres C++ travaillant avec la STL pour la première fois.

En Python, extension d'une liste avec une autre liste utilise le .extend méthode:

>>> v = [1, 2, 3]
>>> v_prime = [4, 5, 6]
>>> v.extend(v_prime)
>>> print(v)
[1, 2, 3, 4, 5, 6]

J'utilise actuellement cette approche algorithmique pour étendre les vecteurs en C++:

v.resize(v.size() + v_prime.size());
copy(v_prime.begin(), v_prime.end(), v.rbegin());

Est-ce la manière canonique d'étendre les vecteurs ou s'il manque un moyen plus simple?

41
cdleary

De ici

// reserve() is optional - just to improve performance
v.reserve(v.size() + distance(v_prime.begin(),v_prime.end()));
v.insert(v.end(),v_prime.begin(),v_prime.end());
66
Dmitry Khalatov
copy(v_prime.begin(), v_prime.end(), back_inserter(v));
20
CTT

Il existe plusieurs façons d'atteindre votre cible.

std :: vecteur :: insérer

Le vecteur peut être étendu en insérant de nouveaux éléments avant l'élément à la position spécifiée, augmentant efficacement la taille du conteneur par le nombre d'éléments insérés. Vous pouvez suivre l'une des approches ci-dessous. La deuxième version utilise C++ 11 et peut être considérée comme une réponse plus générique, car B pourrait également être un tableau.

a.insert(a.end(), b.begin(), b.end());
a.insert(std::end(a), std::begin(b), std::end(b));

Parfois, à usage, il est une meilleure pratique d'utiliser une fonction de réserve avant d'utiliser std :: vecteur :: insert. std :: vecteur :: vecteur La fonction augmente la capacité du conteneur à une valeur supérieure ou égale à new_cap. Si NEW_CAP est supérieur à la capacité actuelle (), le nouveau stockage est attribué, sinon la méthode ne fait rien.

a.reserve(a.size() + distance(b.begin(), b.end()));

L'utilisation de la fonction de réserve n'est pas requise mais peut être souhaitable. Et il est préférable d'utiliser la réserve si vous insérez à plusieurs reprises dans un vecteur pour lequel vous connaissez la taille finale et que cette taille est grande. Sinon, il est préférable de laisser la STL pousser votre vecteur au besoin.

std :: copie

sTD :: Copie est la deuxième option que vous pouvez envisager d'atteindre votre cible. Cette fonction copie les éléments de la plage (premier, dernier) dans la plage commençant en résultat.

std::copy (b.begin(), b.end(), std::back_inserter(a));

Cependant, l'utilisation de std :: copie est plus lente que l'utilisation de std :: vecteur :: insert (), car std :: copy (copy (Copy () ne peut pas réserver assez d'espace avant la main (il n'a pas accès au vecteur lui-même, Seulement à un itérateur qui a), tandis que STD :: vecteur :: insert (), une fonction de membre peut. En raison de cette STD :: La copie est effectivement plus lente que d'utiliser std :: vecteur :: insert. La plupart des gens, sur l'utilisation de STD :: Copier sans connaître ce scénario.

boost :: push_back

La troisième option que vous pouvez envisager est l'utilisation de la fonction de boost push_back.

boost::Push_back(a, b);
7
Tharindu Kumara

J'avais besoin de deux variantes différentes de la fonction extend dans C++ 14, où l'on prend en charge la sémantique de déplacement de chaque élément du vecteur à annexier.

vec est votre v et ext est votre v_prime.

/**
 * Extend a vector with elements, without destroying source one.
 */
template<typename T>
void vector_extend(std::vector<T> &vec, const std::vector<T> &ext) {
    vec.reserve(vec.size() + ext.size());
    vec.insert(std::end(vec), std::begin(ext), std::end(ext));
}

/**
 * Extend a vector with elements with move semantics.
 */
template<typename T>
void vector_extend(std::vector<T> &vec, std::vector<T> &&ext) {
    if (vec.empty()) {
        vec = std::move(ext);
    }
    else {
        vec.reserve(vec.size() + ext.size());
        std::move(std::begin(ext), std::end(ext), std::back_inserter(vec));
        ext.clear();
    }
}
2
TheJJ

En utilisant std::vector::insert ;

A.reserve(A.size() + B.size());
A.insert(A.end(), B.begin(), B.end());

reserve() est facultatif, mais l'utilisation de cela aide à améliorer les performances.


Générateur de code de conviennent pour sauver des secondes précieuses:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css"><script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script><script src="https://cdn.jsdelivr.net/clipboard.js/1.6.0/clipboard.min.js"></script><script>function generateCode(){codeTemplate="{0}.reserve({0}.size() + {1}.size()); \n{0}.insert({0}.end(), {1}.begin(), {1}.end());",first=document.getElementById("1").value,second=document.getElementById("2").value,""==first&&(first="A"),""==second&&(second="B"),document.getElementById("c").innerHTML=String.format(codeTemplate,first,second)}String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!=typeof b[c]?b[c]:a})});</script><div class="A" style="margin:3% 10% 1% 10%;"><label for="1">First vector name:</label><input id="1"/><br/><label for="1">Second vector name:</label><input id="2"/><div class="D"><a class="waves-effect waves-light btn red col" onclick="generateCode();" style="margin:0 0 4% 0;">Generate Code</a></div><textarea id="c" onclick="this.select()" style="border:none;height:auto;overflow: hidden;font-family:Consolas,Monaco;">A.reserve(A.size() + B.size());&#13;&#10;A.insert(A.end(), B.begin(), B.end());</textarea></div>
2
noɥʇʎԀʎzɐɹƆ