J'ai un vecteur d'octets et je souhaite remplacer chaque [1, 2, 3]
par [4, 5, 6]
. Comment est-ce possible dans Rust?
let mut buf = vec![1, 2, 3, 7, 8]; // ? assert_eq!(buf, vec![4, 5, 6, 7, 8]);
3 Réponses :
Cette fonction peut faire le travail:
fn main() { let mut buf = vec![1, 2, 3, 3, 4, 1, 2, 3]; replace_slice(&mut buf[..], &[1, 2, 3], &[5, 1, 2]); assert_eq!(buf, vec![5, 1, 2, 3, 4, 5, 1, 2]); }
Cette fonction est récursive mais vous pouvez également la réécrire en utilisant des boucles.
Exemple 1 :
fn main() { let mut buf = vec![1, 2, 3, 7, 8, 1, 2, 3]; replace_slice(&mut buf[..], &[1, 2, 3], &[4, 5, 6]); assert_eq!(buf, vec![4, 5, 6, 7, 8, 4, 5, 6]); }
Exemple 2: (D'après le commentaire de trentcl)
fn replace_slice<T>(source: &mut [T], from: &[T], to: &[T]) where T: Clone + PartialEq, { let iteration = if source.starts_with(from) { source[..from.len()].clone_from_slice(to); from.len() } else { 1 }; if source.len() > from.len() { replace_slice(&mut source[iteration..], from, to); } }
Sans récursivité:
fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T]) where T: Clone + PartialEq, { for i in 0..=buf.len() - from.len() { if buf[i..].starts_with(from) { buf[i..(i + from.len())].clone_from_slice(to); } } }
Vous pouvez envisager de changer votre boucle en ceci: for i in 0 .. = buf.len () - from.len ()
pour sauter les vérifications inutiles.
@ ÖmerErden source.len () - from.len ()
paniquera lorsque from
est plus grand que source
.
@trentcl merci de l'avoir signalé, il paniquera également lorsque "from" et "to" ne sont pas de taille égale, en raison d'une assertion dans "starts_with". L'ajout de gardes avant la boucle aidera.
@ ÖmerErden starts_with
ne panique pas si self
et aiguille
sont de tailles différentes; il renvoie simplement false
.
@trentcl désolé ça devrait être "clone_from_slice"
Cela fonctionne lorsque les tranches ont des longueurs différentes (similaire à replace
pour str
):
fn replace<T>(source: &[T], from: &[T], to: &[T]) -> Vec<T> where T: Clone + PartialEq { let mut result = source.to_vec(); let from_len = from.len(); let to_len = to.len(); let mut i = 0; while i + from_len <= result.len() { if result[i..].starts_with(from) { result.splice(i..i + from_len, to.iter().cloned()); i += to_len; } else { i += 1; } } result }
La tranche de remplacement a-t-elle nécessairement la même longueur que la tranche à remplacer? Ou pourriez-vous avoir à réduire / agrandir le
Vec
?Je ne pense pas qu'il y ait actuellement de routine générale pratique définie sur
& [u8]
qui le fasse pour vous, similaire à la méthodestr :: replace
. Je l'implémenterais probablement moi-même, éventuellement en copiant le implémentation pourstr :: replace
. (Je travaille sur une bibliothèque de chaînes d'octets pour Rust, qui supportera certainement des opérations comme celle-ci. Mais ce n'est pas encore fini.)Copie possible de Comment copier idiomatiquement une tranche?
L'application de la question liée ici suggère
buf [0..3] .copy_from_slice (& [4, 5, 6]);
. Si les tranches ne sont pas de la même taille, il s'agit probablement d'un doublon de Insérez ou remplacez efficacement plusieurs éléments au milieu ou au début d'un Vec ? à la placeMon erreur, j'ai oublié le mot «chaque» dans la question. Mais les liens ci-dessus sont toujours bons à regarder.
Autre question: si vous remplacez
[1, 2, 3]
par[5, 1, 2]
dans[1, 2, 3, 3] code>, attendez-vous
[5, 1, 2, 3]
? Les deux réponses existantes vous donneront[5, 5, 1, 2]
.@trentcl title pour les points d'interrogation: "remplacer une sous-tranche d'un octet Vec / slice par une autre tranche?" . Ce n'est pas valable pour votre deuxième cas car vous ne remplacez pas le dernier élément (" 3 ") par une autre tranche (juste en remplaçant par un élément qui provient d'un autre tranche )
@ ÖmerErden C'est ce que je veux dire . J'ai pris la fonction
replace_slice
directement à partir de votre réponse. Je ne m'attends pas à ce que ce comportement soit ce que souhaite OP.@trentcl je vois, merci d'avoir mis à jour le code maintenant cela fonctionne aussi avec votre cas.
Voir aussi Comment puis-je trouver une sous-séquence dans un & [ u8] tranche? .