0
\$\begingroup\$

The following sample code is for finding DIGIT_WORDS and their first occurrence in sentence line (Rust Playground)

fn main() {
    const DIGIT_WORDS: &'static [&'static str] = &[
        "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
    ];

    let line = "threehpbsevenffnqgdjcftjkdjhhk7dvzmkmqthreefflb";

    let result: Vec<_> = DIGIT_WORDS
        .iter()
        .filter(|word| line.contains(*word))
        .map(|word| (word, line.find(word).unwrap()))
        .collect();
        
    println!("{:?}", result);  //output: [("three", 0), ("seven", 8)]
}

Not sure how could I combine the filter and map into one filter_map? I tried to use filter_map and str::find but the unwrap will fail if the word doesn't exist in the sentence.

\$\endgroup\$
5
  • \$\begingroup\$ The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ Jan 18 at 7:56
  • \$\begingroup\$ Sorry how could the question title be more specific? Would you mind guiding me? Thanks \$\endgroup\$
    – Winston
    Jan 18 at 23:14
  • 1
    \$\begingroup\$ A better title that follows this community's standards might be something like "Print words and indices of first occurrences found in line". As Toby mentioned, the general guideline for titles in this community is that titles "should reflect what your code does, not what concerns you have about your code". \$\endgroup\$
    – Setris
    Jan 19 at 5:49
  • \$\begingroup\$ In any case, it's not clear that you have finished this code. Asking for a re-write with different constraints is specifically off-topic here. \$\endgroup\$ Jan 19 at 6:42
  • \$\begingroup\$ Someone told me that if I have non working code then I go to stackoverflow. If I have code improvement then I go to codereview. \$\endgroup\$
    – Winston
    Jan 19 at 6:51

2 Answers 2

3
\$\begingroup\$

Code (Rust Playground):

fn main() {
    const DIGIT_WORDS: [&str; 9] = [
        "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
    ];

    let line = "threehpbsevenffnqgdjcftjkdjhhk7dvzmkmqthreefflb";

    let result: Vec<_> = DIGIT_WORDS
        .iter()
        .filter_map(|word| line.find(word).map(|index| (*word, index)))
        .collect();

    println!("{:?}", result);
}

Explanation: I see that you've answered your own question and figured out that the supplied closure to filter_map must return an Option.

A more concise way of writing what you are currently doing with the match keyword in your answer (morphing an Option<usize> into an Option<(&str, usize)>) is by calling map on the Option<usize> returned by str::find and having the supplied closure to map return a (&str, usize), as shown in the above snippet.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks. It seems the filter_map can remove the None by itself and I don't need to use unwrap. Thanks \$\endgroup\$
    – Winston
    Jan 18 at 23:13
0
\$\begingroup\$

I successfully replace filter and map with filter_map

let result: Vec<_> = DIGIT_WORDS
    .iter()
    .filter_map(|word| {
                match line.find(*word) {
                    Some(index) => Some((word, index)),
                    None => None
                }
            })
    .collect();

Just wonder if there are some solution with less line of code

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.