Nate Houk
Nate Houk

Reputation: 365

How to make this iterator/for loop idiomatic in Rust

How can I get rid of the ugly let mut i = 0; and i += 1;? Is there a more idomatic way I can write this loop? I tried .enumerate() but it doesn't work on a &[&str].

use std::fmt::Write;

pub fn build_proverb(list: &[&str]) -> String {
    let mut proverb = String::new();
    let mut i = 0;
    for word in list {
        i += 1;
        if i < list.len() {
            write!(proverb, "For want of a {} the {} was lost.\n", word, list[i]);
        } else {
            write!(proverb, "And all for the want of a {}.", list[0]);
        }
    }
    proverb
}

Upvotes: 1

Views: 171

Answers (1)

cameron1024
cameron1024

Reputation: 10136

You were close, enumerate() doesn't exist for &[&str] because enumerate() is a function on Iterator, and &[&str] is not an Iterator.

But you can call list.iter() to get an iterator, which you can then call enumerate() on.

Full example:

pub fn build_proverb(list: &[&str]) -> String {
    let mut proverb = String::new();
    for (i, word) in list.iter().enumerate() {
        if i < list.len() {
            write!(proverb, "For want of a {} the {} was lost.\n", word, list[i]);
        } else {
            write!(proverb, "And all for the want of a {}.", list[0]);
        }
    }
    proverb
}

The fact you have word and list[i] (after incrementing i) makes it look like you want something like windows:

pub fn build_proverb(list: &[&str]) -> String {
    let mut proverb = String::new();

    for words in list.windows(2) {
        let first = words[0];
        let second = words[1];
        write!(proverb, "For want of a {} the {} was lost.\n", first, second);
    }
    write!(proverb, "And all for the want of a {}.", list[0]);
    proverb
}

Upvotes: 4

Related Questions