0

So I'm following with the Rust Book tutorial on writing a grep clone with Rust. The book at first gives the example of this function to search a file for a given string:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}

Which I then modified to that results would include the line number the match was found on, like so:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<String> {
    let mut results = Vec::new();

    for (index, line) in contents.lines().enumerate() {
        if line.to_lowercase().contains(&query) {
            let line_found = &index + 1;
            results.push(String::from(format!("Line {line_found}: {line}")));
        }
    }

    results
}

So then afterwards, the books shows how to use an iterator to make the code simpler and cleaner:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents
        .lines()
        .filter(|line| line.contains(query))
        .collect()
}

And I'm struggling to figure out how I would obtain the same functionality to include the line number the match was found on with this function. In collect() is there a way for me access the index of the iterator and the line itself?

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Luke
  • 155
  • 1
  • 10

1 Answers1

0

Use enumerate, which transforms an Iterator<Item = T> to an Iterator<Item = (usize, T)> where the first element of the tuple is your index. You already used it in your second example, it can be used in the transformed version as well since it's still an iterator combinator.

naiveai
  • 590
  • 2
  • 14
  • 42