Home > Software engineering >  Get index of first occurrence of any of range of values in string
Get index of first occurrence of any of range of values in string

Time:07-16

I'm trying to find the index of the first vowel in a string (English/ASCII only). I need to extract this index to use it later on (returned in this example). This works:

let s = String::from("cats");

let vowels = ['a', 'e', 'i', 'o', 'u'];

for v in vowels {
    let index = s.to_lowercase().find(v);
    if let Some(i) = index {
        return i;
    }
    break;
}

This works fine, but I feel like there should be a more concise way to do this. Every oneliner I try returns a bool that there was a match or an iterator in vowels rather than the index in the string, s. Help?

CodePudding user response:

Use the .position() method on a .chars() iterator:

let string = "cats".to_owned();
let vowels = ['a', 'e', 'i', 'o', 'u'];

if let Some(index) = string.chars().position(|c| vowels.contains(&c)) {
    println!("found first vowel at position: {}", index);
}

Note that this inverts your iteration since your original code would return the first "a" in the string even if there were other vowels before it.


I'd also be remiss if I didn't point out the distinction between character index vs byte index. If you're using ASCII text only then there's no difference, but if you want to be unicode aware and want "the vowel is the nth character", then you'll want to use .char_indices() and .find() instead:

let string = "ćats".to_owned(); // ć is a multi-byte character
let vowels = ['a', 'e', 'i', 'o', 'u'];

if let Some(index) = string.chars().position(|c| vowels.contains(&c)) {
    println!("found first vowel at character: {}", index);
}

if let Some((index, _)) = string.char_indices().find(|(i, c)| vowels.contains(&c)) {
    println!("found first vowel at byte offset: {}", index);
}
found first vowel at character: 1
found first vowel at byte offset: 2

What you want depends on how you'll use the index. You'd want the byte offset if you were to index into the string later (for example, get the sub-string before the vowel: &string[..index]).

  • Related