2016-05-11 32 views
8

Ho esaminato la Rust docs for String ma non riesco a trovare un modo per estrarre una sottostringa.Esiste un metodo come il substr di JavaScript in Rust?

Esiste un metodo come JavaScript substr in Rust? Altrimenti, come lo implementeresti?

str.substr(start[, length]) 

Il più vicino è probabilmente slice_unchecked ma utilizza scostamenti di byte invece di indici di carattere ed è contrassegnato unsafe.

risposta

11

Per i caratteri, è possibile utilizzare s.chars().skip(pos).take(len):

fn main() { 
    let s = "Hello, world!"; 
    let ss: String = s.chars().skip(7).take(5).collect(); 
    println!("{}", ss); 
} 

Attenzione della definizione dei caratteri Unicode però.

Per byte, è possibile utilizzare la sintassi slice:

fn main() { 
    let s = "Hello, world!"; 
    let ss = &s[7..12]; 
    println!("{}", ss); 
} 
+0

non vide 'caratteri()', grazie! Sarebbe anche possibile mappare l'indice char su un offset di byte e creare una sezione da questo? – laktak

+2

@laktak, puoi usare 'str :: char_indices' per quello. https://doc.rust-lang.org/std/primitive.str.html#method.char_indices – WiSaGaN

9

È possibile utilizzare il metodo as_str sul Chars iteratore per tornare una fetta &str dopo aver calpestato l'iteratore. Quindi, per saltare i primi start caratteri, è possibile chiamare

let s = "Some text to slice into"; 
let mut iter = s.chars(); 
iter.by_ref().nth(start); // eat up start values 
let slice = iter.as_str(); // get back a slice of the rest of the iterator 

Ora, se anche voi volete limitare la lunghezza, è necessario prima di capire il byte-posizione del carattere length:

let end_pos = slice.char_indices().nth(length).map(|(n, _)| n).unwrap_or(0); 
let substr = &slice[..end_pos]; 

Questo potrebbe sembrare un po 'tondo, ma Rust non ti nasconde nulla che potrebbe occupare dei cicli della CPU. Detto questo, mi chiedo perché non ci sia ancora una cassa che offra un metodo substr.

+0

"non nascondendo nulla da te che potrebbe richiedere cicli di CPU" - puoi spiegare perché substr potrebbe essere più costoso di le funzioni di assetto che ha? – laktak

+1

Bene ... ci si aspetta che le funzioni di assetto si liberino di tutti gli spazi bianchi che incontrano. Questa è un'operazione O (n) per definizione. Ma usando un metodo 'substr', l'utente potrebbe supporre che sia O (1), perché stanno inserendo indici. –

1

Per my_string.substring(start, len) -come la sintassi, è possibile scrivere un tratto personalizzato:

trait StringUtils { 
    fn substring(&self, start: usize, len: usize) -> Self; 
} 

impl StringUtils for String { 
    fn substring(&self, start: usize, len: usize) -> Self { 
     self.chars().skip(start).take(len).collect() 
    } 
} 

// Usage: 
fn main() { 
    let phrase: String = "this is a string".to_string(); 
    println!("{}", phrase.substring(5, 8)); // prints "is a str" 
}