In Rust, what's the idiomatic way to split a &str into an iterator of &strs of one character each?

烂漫一生 提交于 2020-04-13 14:52:16

问题


If I want to take a &str like "aeiou" and turn it into an iterator roughly equivalent to ["a", "e", "i", "o", "u"].iter(), what's the most idiomatic way to do it?

I've tried doing "aeiou".split("") which seemed idiomatic to me, but I got empty &strs at the beginning and end.

I've tried doing "aeiou".chars() but it got pretty ugly and unwieldy from there trying to turn the chars into &strs.

For the time being, I just typed out ["a", "e", "i", "o", "u"].iter(), but there's got to be an easier, more idiomatic way.

For context, I'm eventually going to be looping over each value and passing it into something like string.matches(vowel).count().

Here's my overall code. Maybe I went astray somewhere else.

fn string_list_item_count<'a, I>(string: &str, list: I) -> usize
where
    I: IntoIterator<Item = &'a str>,
{
    let mut num_instances = 0;

    for item in list {
        num_instances += string.matches(item).count();
    }

    num_instances
}

// snip

string_list_item_count(string, vec!["a", "e", "i", "o", "u"])

// snip

If I could make string_list_item_count accept the std::str::pattern::Pattern trait inside the iterator, I think that would make this function accept iterators of &str and char, but the Pattern trait is a nightly unstable API and I'm trying to avoid using those.


回答1:


You can use split_terminator instead of split to skip the empty string at the end of the iterator. Additionally, if you skip the first element of the iterator, you get the result you want:

let iterator = "aeiou".split_terminator("").skip(1);
println!("{:?}", iterator.collect::<Vec<_>>());

Output:

["a", "e", "i", "o", "u"]



回答2:


I would use str::split with an empty string and then remove any empty strings using Iterator::filter:

fn string_chars(s: &str) -> impl Iterator<Item = &str> {
    s.split("").filter(|s| !s.is_empty())
}

fn main() {
    assert_eq!(
        string_chars("aeiou").collect::<Vec<_>>(),
        ["a", "e", "i", "o", "u"],
    );
}



回答3:


A closure can also serve as a Pattern:

fn main() {
    let vowels = "aeiou";
    let s = "the quick brown fox jumps over the lazy dog";
    let count = string_item_count(s, vowels);
    dbg!(count);
}

fn string_item_count(string: &str, pat: &str) -> usize {
    let pred = |c| pat.contains(c);
    string.matches(pred).count()
}


来源:https://stackoverflow.com/questions/59597751/in-rust-whats-the-idiomatic-way-to-split-a-str-into-an-iterator-of-strs-of-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!