如何迭代一个字符列表,同时仍能在迭代中跳过?

时间:2017-07-15 20:25:54

标签: while-loop rust iteration chars

我有以下代码:

let mut lex_index = 0;
let chars = expression.chars();
while lex_index < chars.count() {
    if(chars[lex_index] == "something") {
        lex_index += 2;
    } else {
        lex_index += 1;
    }
}

我在这里使用while循环,因为我有时需要跳过chars中的字符。 但是,这给了我以下错误:

error[E0382]: use of moved value: `chars`
  --> src/main.rs:23:15
   |
23 |     while i < chars.count() {
   |               ^^^^^ value moved here in previous iteration of loop
   |
   = note: move occurs because `chars` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait

2 个答案:

答案 0 :(得分:7)

迭代某些内容而不是使用索引更好:

let mut chars = "gravy train".chars().fuse();

while let Some(c) = chars.next() {
    if c == 'x' {
        chars.next(); // Skip the next one
    }
}

我们fuse迭代器,以避免在返回第一个next后调用None时遇到任何问题。

您的代码存在许多问题:

  1. Iterator::count使用迭代器。一旦你调用了它,迭代器就会消失。这是导致错误的原因。另一种解决方案是使用Iterator::by_ref,以便消耗你计算的迭代器不是行的结尾。

  2. chars属于Chars类型,不支持索引编制。 chars[lex_index]是荒谬的。

  3. 您无法将char与字符串进行比较,因此chars[lex_index] == "something"也无法编译。您可以使用Chars::as_str,但是您必须放弃Fuse并自行处理。

答案 1 :(得分:2)

您可以使用strcursor包装箱:

extern crate strcursor;

fn main() {
    use strcursor::StrCursor;
    let expr = r"abc\xdef";
    let mut cur = StrCursor::new_at_start(expr);

    // `after`: the next grapheme cluster
    while let Some(gc) = cur.after() {
        if gc == "\\" {
            // Move right two grapheme clusters.
            cur.seek_next();
            cur.seek_next();
        } else {
            print!("{}", gc);
            cur.seek_next();
        }
    }
    println!("");
}

// Output: `abcdef`