2015-07-07 10 views
6

Ho un file nel formato csv con una prima colonna di dati che rappresenta il codice articolo opzionalmente terminato con "UNIUNI" o caso misto di questi caratteri, caricato mediante un lettore di codici a barre. Devo tagliare via l'ultimo "UNI" s.Taglio efficiente di una stringa

A Rust ho provato a scrivere con successo parziale di una funzione essenzialmente come questo:

fn main() { 
    // Ok: from "9846UNIUNI" to "9846" 
    println!("{}", read_csv_rilev("9846UNIUNI".to_string())); 

    // Wrong: from "9846uniuni" to "9846" 
    println!("{}", read_csv_rilev("9846uniuni".to_string())); 
} 

fn read_csv_rilev(code: String) -> String { 
    code 
     //.to_uppercase() /*Unstable feature in Rust 1.1*/ 
     .trim_right_matches("UNI") 
     .to_string() 
} 

La firma della funzione ideale assomiglia:

fn read_csv_rilev(mut s: &String) {/**/} 

ma probabilmente un'azione sul posto on a String non è una buona idea In effetti, nella libreria standard di Rust non c'è nulla da fare, escluso String::pop().

C'è un modo per applicare il taglio su una stringa senza allocarne un altro?

+2

'.trim_right_matches()' sta per essere stabile a Rust 1.2 – bluss

+0

E '.trim_right()', che puoi usare per farlo senza '.to_string()'. Basta usare la lunghezza dello str tagliato per troncare. – bluss

risposta

7

un modo per applicare il taglio su una stringa senza allocarne un altro?

Sì, utilizzando truncate:

const TRAILER: &'static str = "UNI"; 

fn read_csv_rilev(s: &mut String) { 
    while s.ends_with(TRAILER) { 
     let len = s.len(); 
     let new_len = len.saturating_sub(TRAILER.len()); 
     s.truncate(new_len); 
    } 
} 

fn main() { 
    let mut code = "Hello WorldUNIUNIUNI".into(); 

    read_csv_rilev(&mut code); 

    println!("{}", code); 
} 

Naturalmente, non si necessità di pasticciare con la stringa assegnata a tutti. È possibile utilizzare la stessa logica e creare sottosezioni successive della stringa. Questo è fondamentalmente how trim_right_matches opere, ma un po 'meno generico:

const TRAILER: &'static str = "UNI"; 

fn read_csv_rilev(mut s: &str) -> &str { 
    while s.ends_with(TRAILER) { 
     let len = s.len(); 
     let new_len = len.saturating_sub(TRAILER.len()); 
     s = &s[..new_len]; 
    } 
    s 
} 

fn main() { 
    let code = "Hello WorldUNIUNIUNI"; 

    let truncated = read_csv_rilev(code); 

    println!("{}", truncated); 
} 

In generale, probabilmente sarei andare con la seconda soluzione.

+0

Grazie. Ho imparato più di una cosa. – robitex

3

ma probabilmente un'azione sul posto su una stringa non è una buona idea.

Il vincolante è mutevole in mut s: &String, non la stringa stessa. Prenderesti s: &mut String se volessi modificare la stringa stessa.

Detto questo, non penso che ci sia qualcosa nella libreria standard per farlo.

+0

Grazie, Steve. Sei nel giusto. A volte le mani sulla tastiera non sono collegate così bene ... :-) – robitex

+0

Va tutto bene! È una cosa sottile :) –

2

Un'altra soluzione è quella di utilizzare il owning_ref cassa, che consente di ritorni sia un &str e il suo sostegno String allo stesso tempo:

extern crate owning_ref; 
use owning_ref::StringRef; 

fn read_csv_rilev(code: String) -> StringRef { 
    StringRef::new(code).map(|s| s.trim_right_matches("UNI")) 
}