Supposons que j'ai le vecteur suivant:
std::vector<int> data{0,1,2,3,4};
Je voudrais remplacer la séquence {1,2,3} par un seul nombre. J'ai trouvé un exemple avec std :: replace mais là, un seul numéro est remplacé par un autre numéro unique. Comment remplacer une séquence en vecteur?
5 Réponses :
Premièrement: vector :: effacer
// inserting into a vector #include <iostream> #include <vector> int main () { std::vector<int> myvector (3,100); std::vector<int>::iterator it; it = myvector.begin(); it = myvector.insert ( it , 200 ); myvector.insert (it,2,300); // "it" no longer valid, get a new one: it = myvector.begin(); std::vector<int> anothervector (2,400); myvector.insert (it+2,anothervector.begin(),anothervector.end()); int myarray [] = { 501,502,503 }; myvector.insert (myvector.begin(), myarray, myarray+3); std::cout << "myvector contains:"; for (it=myvector.begin(); it<myvector.end(); it++) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
Production: myvector contient: 4 5 7 8 9 10
Ensuite: vector :: insert
// erasing from vector #include <iostream> #include <vector> int main () { std::vector<int> myvector; // set some values (from 1 to 10) for (int i=1; i<=10; i++) myvector.push_back(i); // erase the 6th element myvector.erase (myvector.begin()+5); // erase the first 3 elements: myvector.erase (myvector.begin(),myvector.begin()+3); std::cout << "myvector contains:"; for (unsigned i=0; i<myvector.size(); ++i) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
Vous pouvez peut-être écrire une fonction personnalisée, comme celle-ci:
vector<int> replace_sequence(const vector<int> in,int start,int end,int replace) { vector<int> res; //check the index value if(start<0 || end > in.size() || start > end){ return res; } int distance = end -start; //construct the result for(int i=0;i<in.size();i++){ if(i==start){ res.push_back(replace); i+=distance; }else{ res.push_back(in[i]); } } return res; }
bool erase_replace_seq (vector <int>& data, int start, int end, int replace) { bool result = false; if ((start<data.size () && start>=0) && (end < data.size () && end >=0 && end >= start)) { auto iter = data.erase (data.begin () + start, data.begin () + end); data.insert (iter, replace); result = true; } return result; }
Nous pouvons le faire en utilisant std :: vector :: erase (const_iterator en premier, const_iterator en dernier)
comme suit.
La fonction suivante remplace la valeur de org [start]
par val
puis efface les éléments de la plage [start + 1, end]
:
template<class T> std::vector<T> replace( const std::vector<T>& org, std::size_t start, std::size_t end, const T& val) { assert(start <= end); assert(end < org.size()); auto vec(org); auto it_s = vec.begin() + start; *it_s = val; vec.erase(it_s + 1, vec.begin() + end + 1); return vec; }
J'ai généralisé votre question dans n'importe quel conteneur STL en utilisant des paires d'itérateurs au lieu de vecteurs pour l'entrée. L'algorithme comporte 3 étapes:
dernier
s'il n'est pas trouvé Comme les itérateurs ne peuvent pas vraiment effacer les éléments du conteneur, data.erase (newEnd, data.end ());
est nécessaire pour réduire le vecteur.
L'algorithme doit être assez stable et fonctionner même pour les vecteurs à 1 élément.
La fonction peut être déclarée constexpr
depuis C ++ 14.
int main() { std::vector<int> data{0, 1, 2, 3, 4}; replaceSequenceWithValue(data, {1, 2, 3}, 5); for (auto d : data) { std::cout << d << '\n'; } }
Si vous n'avez pas besoin d'une telle généralisation, vous pouvez l'envelopper en fonction avec une signature plus simple :
template <class Value> constexpr void replaceSequenceWithValue(std::vector<Value> &data, const std::vector<Value> &sequence, Value &&value) { auto newEnd = replaceSequenceWithValue(data.begin(), data.end(), sequence.begin(), sequence.end(), std::forward<Value>(value)); data.erase(newEnd, data.end()); }
Et utilisez comme:
#include <algorithm> #include <iostream> #include <vector> template <class ForwardIt1, class ForwardIt2, class Value> constexpr ForwardIt1 replaceSequenceWithValue(ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first, ForwardIt2 s_last, Value &&value) { auto seq_start = std::search(first, last, s_first, s_last); if (seq_start == last) return last; // return last if no seq was found *seq_start = std::forward<Value>(value); auto itemsToBeRemoved = std::distance(s_first, s_last) - 1; // return new end if (itemsToBeRemoved > 0) return std::remove_if(std::next(seq_start), last, [&itemsToBeRemoved](const auto &) { return itemsToBeRemoved-- > 0; }); return last; } int main() { std::vector<int> data{0, 1, 2, 3, 4}; std::vector<int> seq{1, 2, 3}; auto newEnd = replaceSequenceWithValue(data.begin(), data.end(), seq.begin(), seq.end(), 5); data.erase(newEnd, data.end()); for (auto d : data) { std::cout << d << '\n'; } }
Je ne suis pas convaincu de std :: remove_if
ici, mais je ne pourrais rien trouver de mieux. std :: rotate
peut fonctionner, mais il déplacerait des éléments juste pour être rejetés à la fin du vecteur data
. std :: shift_left
de C ++ 20 serait parfait à utiliser ici.
Supprimez deux des trois valeurs. Remplacez ensuite l'existant.