Come divido una stringa in Rust?


145

Dalla documentazione , non è chiaro. In Java è possibile utilizzare il splitmetodo in questo modo:

"some string 123 ffd".split("123");


@bow Esiste un modo per renderlo un array String anziché un vettore?
Greg,

Non sono a conoscenza di alcun modo per farlo, almeno direttamente. Probabilmente dovresti iterare manualmente su Splite impostarlo nell'array. Ovviamente questo significa che il numero di elementi in ogni divisione deve essere lo stesso poiché le matrici sono di dimensioni fisse e devi avere la matrice definita prima. Immagino che questo possa essere più un problema che semplicemente creare un Vec.
prua il

Risposte:


160

Uso split()

let mut split = "some string 123 ffd".split("123");

Ciò fornisce un iteratore, su cui è possibile eseguire il loop o collect()in un vettore.

for s in split {
    println!("{}", s)
}
let vec = split.collect::<Vec<&str>>();
// OR
let vec: Vec<&str> = split.collect();

15
Puoi anche scriverlo .collect::<Vec<_>>().
Chris Morgan,

come posso ottenere la lunghezza del risultato - let split? split.len()non esiste.
ア レ ッ ク ス

5
@AlexanderSupertramp Use .count(). len()è solo per gli iteratori che conoscono le loro dimensioni esatte senza bisogno di essere consumati, count()consuma l'iteratore.
Manishearth,

error: cannot borrow immutable local variable split` as mutable`
ア レ ッ ク ス

@AlexanderSupertramp let mut split, scusa.
Manishearth,

53

Esistono tre modi semplici:

  1. Per separatore :

    s.split("separator")  |  s.split('/')  |  s.split(char::is_numeric)
  2. Per spazio bianco :

    s.split_whitespace()
  3. Per newline :

    s.lines()

Il risultato di ogni tipo è un iteratore:

let text = "foo\r\nbar\n\nbaz\n";
let mut lines = text.lines();

assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());

assert_eq!(None, lines.next());

29

Esiste un metodo speciale splitper structString :

fn split<'a, P>(&'a self, pat: P) -> Split<'a, P> where P: Pattern<'a>

Dividi per carattere:

let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);

Dividi per stringa:

let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
assert_eq!(v, ["lion", "tiger", "leopard"]);

Dividi per chiusura:

let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
assert_eq!(v, ["abc", "def", "ghi"]);

14

splitrestituisce una Iterator, che è possibile convertire in un Vecutilizzando collect: split_line.collect::<Vec<_>>(). Passare attraverso un iteratore invece di restituire Vecdirettamente ha diversi vantaggi:

  • splitè pigro. Ciò significa che non dividerà davvero la linea fino a quando non ne avrai bisogno. In questo modo non perderai tempo a dividere l'intera stringa se hai bisogno solo dei primi valori: split_line.take(2).collect::<Vec<_>>()o anche se hai bisogno solo del primo valore che può essere convertito in un numero intero:split_line.filter_map(|x| x.parse::<i32>().ok()).next() . Quest'ultimo esempio non perderà tempo nel tentativo di elaborare "23.0", ma interromperà l'elaborazione immediatamente dopo aver trovato "1".
  • splitnon assume alcuna ipotesi sul modo in cui si desidera memorizzare il risultato. Puoi usare a Vec, ma puoi anche usare tutto ciò che implementa FromIterator<&str>, ad esempio a LinkedListo a VecDeque, o qualsiasi tipo personalizzato che implementa FromIterator<&str>.

1
Grazie per la risposta dettagliata, qualche idea sul perché let x = line.unwrap().split(",").collect::<Vec<_>>();non funziona se non è separato in due righe separate: let x = line.unwrap();e let x = x.split(",").collect::<Vec<_>>();? Il messaggio di errore dice:temporary value created here ^ temporary value dropped here while still borrowed
Greg

Comunque funziona come previsto se usolet x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();
Greg

6

C'è anche split_whitespace()

fn main() {
    let words: Vec<&str> = "   foo   bar\t\nbaz   ".split_whitespace().collect();
    println!("{:?}", words);
    // ["foo", "bar", "baz"] 
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.