[rust]イテレータわからん
ひとまず動くコードは作れたけど、ちょっと納得行かない……
問題は言語処理100本ノック #05から
コード
現在のコード
// 05. n-gram
// 与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,"I am an NLPer"という文から単語bi-gram,文字bi-gramを得よ.
fn ngram<T: std::marker::Copy, I: Iterator<Item = T>>(iter: I, n: usize) -> Vec<Vec<T>> {
let r:Vec<T> = iter.collect();
let sz = r.iter().count();
let mut res= Vec::new();
for i in 0..sz-n+1{
res.push(r.iter().skip(i).take(n).copied().collect());
}
res
}
fn main() {
let s = "I am an NLPer";
let r1 = ngram(s.split_whitespace(), 2);
let r2 = ngram(s.chars(), 2);
println!("{:?}", r1);
println!("{:?}", r2);
}
出力
[["I", "am"], ["am", "an"], ["an", "NLPer"]]
[['I', ' '], [' ', 'a'], ['a', 'm'], ['m', ' '], [' ', 'a'], ['a', 'n'], ['n', ' '], [' ', 'N'], ['N', 'L'], ['L', 'P'], ['P', 'e'], ['e', 'r']]
課題
イテレータを引数に渡しているのに、中ですぐcollect()
してから改めてループ処理してるところ。
iter.map(|x| [x, x.next()]).collect()
みたいなことがしたいわけですが
1. x:<T>
でありイテレータではないため、next()
できない
2. 可能だったとして、next()
でイテレータが消費されてしまう
という点が問題になっています。
動いてるのでOKではあるんですが、よりきれいに書ける方法を御存知の方にぜひ教えてほしいです。
0