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_slicedirectement à 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? .