2015-12-04 3 views

ответ

7

Существует адаптер итератора map! Вы бы использовать его как это:

let bar : Vec<u16> = foo.split(",").map(|x| x.parse::<u16>().unwrap()).collect(); 

Тогда parse функция библиотеки, опираясь на черты FromStr, и он может вернуть ошибку, так что нам нужно unwrap() тип ошибки. (Это хорошая идея для краткого примера, но в реальном коде вам нужно правильно обработать ошибку - если у вас есть значение, которое не является u16, ваша программа просто сбой).

map принимает замыкание, которое принимает его параметр по значению, а затем возвращает итератор, полученный lazily, применяя эту функцию. Вы здесь collect, но если вы только take(5) из них, вы будете разбирать только 5 строк.

+0

Решено! Спасибо за хорошее объяснение. – Axuttaja

9

Вы не указали полностью определенную проблему. В частности, что должно произойти, когда одна из строк не может быть обработана в цифре? Когда вы разбираете номер из строки с помощью parse, он может выйти из строя. Поэтому функция возвращает Result:

fn parse<F>(&self) -> Result<F, F::Err> 
    where F: FromStr 

Вот решение, которое принимает вектор, получает итератор с iter, изменяется каждый элемент с помощью map и в конечном счете возвращает Result с помощью collect. Если синтаксический анализ был успешным, вы получите Ok. Если любой не удалось, вы получаете Err:

fn main() { 
    let input = "1,2,3"; 
    let strings: Vec<_> = input.split(",").collect(); 

    let numbers: Result<Vec<u16>, _> = 
     strings.iter().map(|x| x.parse()).collect(); 

    println!("{:?}", numbers); 
} 

Или вы можете удалить неудачные преобразования путем преобразования Result в Option с ok, а затем отфильтровывать None значения с filter_map:

fn main() { 
    let input = "1,2,3"; 
    let strings: Vec<_> = input.split(",").collect(); 

    let numbers: Vec<u16> = 
     strings.iter().filter_map(|x| x.parse().ok()).collect(); 

    println!("{:?}", numbers); 
} 

Из Конечно, это бит глупо, чтобы преобразовать строку в вектор строк, а затем преобразовать ее снова в вектор целых чисел. Если вы на самом деле есть строка разделенных запятыми и хотите цифры, сделать это на одном дыхании:

fn main() { 
    let input = "1,2,3"; 

    let numbers: Result<Vec<u16>, _> = 
     input.split(",").map(|x| x.parse()).collect(); 

    println!("{:?}", numbers); 
} 
3

Мое мнение, как кто-то на самом деле не испытывали в Руст еще.

fn main() { 

    let foo: &str = "1,2,3"; // Parsing a string here 
    let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of str's 

    // here the magic happens 
    let baz = bar.iter().map(|x|x.parse::<i64>()); 

    for x in baz { 
     match x { 
      Ok(i) => println!("{}", i), 
      Err(_) => println!("parse failed") 
     } 
    } 

} 

Обратите внимание, что поскольку parse возвращает Result, вы должны извлечь значение из каждого разбираемого элемента. Вы можете вести себя по-другому, например. фильтруйте только полученные результаты.

Смежные вопросы