2015-07-07 13 views
6

Tôi có tệp ở định dạng csv với cột dữ liệu đầu tiên đại diện cho mã mục tùy chọn kết thúc bằng "UNIUNI" hoặc trường hợp hỗn hợp của các ký tự này, được nạp bằng đầu đọc mã vạch. Tôi cần cắt bỏ số "UNI" s vừa qua.Cắt tỉa hiệu quả một chuỗi

Trong Rust Tôi cố gắng để viết thành công một phần là một chức năng cơ bản như thế này:

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() 
} 

Chữ ký chức năng lý tưởng trông giống như:

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

nhưng có lẽ một hành động tại chỗ trên một String không phải là một ý tưởng hay. Trong thực tế, trong thư viện chuẩn Rust không có gì để làm điều này, ngoại trừ String::pop().

Có cách nào để áp dụng trang trí trên Chuỗi không phải phân bổ một chuỗi khác không?

+2

'.trim_right_matches() 'sẽ được ổn định ở Rust 1.2 – bluss

+0

Và '.trim_right()', mà bạn có thể sử dụng để làm điều này mà không có '.to_string()'. Chỉ cần sử dụng độ dài của đường cắt để cắt ngắn. – bluss

Trả lời

7

một cách để áp dụng cắt tỉa trên Chuỗi mà không cần phân bổ một chuỗi khác?

Vâng, sử dụng 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); 
} 

Tất nhiên, bạn không cần để gây rối với các chuỗi phân bổ ở tất cả. Bạn có thể sử dụng cùng một logic và tạo ra các subslices liên tiếp của chuỗi. Đây là cơ bản như thế nào trim_right_matches công trình, nhưng một chút ít generic:

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); 
} 

Nói chung, tôi có thể đi với giải pháp thứ hai.

+0

Cảm ơn bạn. Tôi đã học được nhiều thứ. – robitex

3

nhưng có thể hành động tại chỗ trên chuỗi không phải là một ý tưởng hay.

Các ràng buộc là có thể thay đổi trong mut s: &String, không phải là chuỗi riêng của mình. Bạn sẽ mất s: &mut String nếu bạn muốn thay đổi chính chuỗi đó.

Điều đó nói rằng, tôi không nghĩ có bất kỳ điều gì trong thư viện chuẩn để thực hiện việc này.

+0

Cảm ơn bạn Steve. Bạn đang ở bên phải. Đôi khi bàn tay trên bàn phím không được kết nối rất tốt ... :-) – robitex

+0

Đó là tất cả tốt! Đó là một điều tinh tế :) –

2

Một giải pháp khác là sử dụng owning_ref thùng, cho phép bạn quay trở lại cả một &str và sự ủng hộ của mình String cùng một lúc:

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")) 
} 
Các vấn đề liên quan