从特定索引处的迭代器中收集项目

时间:2015-08-13 11:15:07

标签: rust

我想知道是否可以在迭代器上使用.collect()来获取特定索引处的项目。例如,如果我以字符串开头,我通常会这样做:

let line = "Some line of text for example";
let l = line.split(" ");
let lvec: Vec<&str> = l.collect();
let text = &lvec[3];

但最好的是:

let text: &str = l.collect(index=(3));

4 个答案:

答案 0 :(得分:12)

不,不是;但是,在收集之前,您可以轻松过滤,这实际上可以达到同样的效果。

如果您希望按索引进行过滤,则需要添加索引,然后将其删除:

  • enumerate(将索引添加到元素中)
  • filter基于此索引
  • map从元素
  • 中删除索引

或代码:

fn main() {
    let line = "Some line of text for example";
    let l = line.split(" ")
                .enumerate()
                .filter(|&(i, _)| i == 3 )
                .map(|(_, e)| e);
    let lvec: Vec<&str> = l.collect();
    let text = &lvec[0];
    println!("{}", text);
}

如果您只想获得单个索引(以及元素),那么使用nth会更容易。它在这里返回Option<&str>,您需要注意:

fn main() {
    let line = "Some line of text for example";
    let text = line.split(" ").nth(3).unwrap();
    println!("{}", text);
}

如果你可以拥有一个任意谓词,但只希望匹配的第一个元素,那么收集到Vec是低效的:它将消耗整个迭代器(没有懒惰)并且可能分配大量的内存。根本不需要。

因此,您最好只使用迭代器的next方法请求第一个元素,该方法在此处返回Option<&str>

fn main() {
    let line = "Some line of text for example";
    let text = line.split(" ")
                   .enumerate()
                   .filter(|&(i, _)| i % 7 == 3 )
                   .map(|(_, e)| e)
                   .next()
                   .unwrap();
    println!("{}", text);
}

如果你想通过索引选择结果的部分,你也可以在收集之前使用skiptake,但我猜你这里有足够的选择已经

答案 1 :(得分:9)

nth上有一个Iterator函数执行此操作:

let text = line.split(" ").nth(3).unwrap();

答案 2 :(得分:2)

没有;不过,您可以使用takenext

let line = "Some line of text for example";
let l = line.split(" ");
let text = l.skip(3).next();

请注意,这会导致text成为Option<&str>,因为不能保证序列实际至少有至少四个元素。

附录:使用nth肯定会更短,但我更愿意明确访问 n th 迭代器的元素必须消耗之前的所有元素。

答案 3 :(得分:0)

对于任何可能感兴趣的人,你可以用迭代器做很多很酷的事情(感谢Matthieu M),例如根据索引从字符串中获取多个'words',你可以使用filter与逻辑或||一起测试多个索引!

let line = "FCC2CCMACXX:4:1105:10758:14389# 81 chrM 1 32 10S90M = 16151 16062"
let words: Vec<&str> = line.split(" ")
                           .enumerate()
                           .filter(|&(i, _)| i==1 || i==3 || i==6 )
                           .map(|(_, e) | e)
                           .collect();