在 Rust 中,将 &str 拆分为每个一个字符的 &strs 的迭代器的惯用方法是什么?
In Rust, what's the idiomatic way to split a &str into an iterator of &strs of one character each?
如果我想像 "aeiou"
这样的 &str
并将其转换为大致相当于 ["a", "e", "i", "o", "u"].iter()
的迭代器,最惯用的方法是什么?
我试过做 "aeiou".split("")
,这对我来说似乎是惯用的,但我在开头和结尾都得到了空的 &str
。
我已经尝试过 "aeiou".chars()
,但是从那里试图将 char
s 变成 &str
s 变得非常丑陋和笨拙。
目前,我只是输入 ["a", "e", "i", "o", "u"].iter()
,但必须有更简单、更惯用的方式。
对于上下文,我最终将遍历每个值并将其传递给类似 string.matches(vowel).count()
.
的内容
这是我的整体代码。也许我在别的地方误入歧途了。
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
如果我能让 string_list_item_count
接受迭代器中的 std::str::pattern::Pattern
特征,我认为这将使这个函数接受 &str
和 char
的迭代器,但是Pattern
特性是夜间不稳定的 API,我正在努力避免使用它们。
你可以使用split_terminator
instead of split
to skip the empty string at the end of the iterator. Additionally, if you skip
迭代器的第一个元素,你得到你想要的结果:
let iterator = "aeiou".split_terminator("").skip(1);
println!("{:?}", iterator.collect::<Vec<_>>());
输出:
["a", "e", "i", "o", "u"]
闭包也可以作为 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()
}
我会使用 str::split
和空字符串,然后使用 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"],
);
}
如果我想像 "aeiou"
这样的 &str
并将其转换为大致相当于 ["a", "e", "i", "o", "u"].iter()
的迭代器,最惯用的方法是什么?
我试过做 "aeiou".split("")
,这对我来说似乎是惯用的,但我在开头和结尾都得到了空的 &str
。
我已经尝试过 "aeiou".chars()
,但是从那里试图将 char
s 变成 &str
s 变得非常丑陋和笨拙。
目前,我只是输入 ["a", "e", "i", "o", "u"].iter()
,但必须有更简单、更惯用的方式。
对于上下文,我最终将遍历每个值并将其传递给类似 string.matches(vowel).count()
.
这是我的整体代码。也许我在别的地方误入歧途了。
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
如果我能让 string_list_item_count
接受迭代器中的 std::str::pattern::Pattern
特征,我认为这将使这个函数接受 &str
和 char
的迭代器,但是Pattern
特性是夜间不稳定的 API,我正在努力避免使用它们。
你可以使用split_terminator
instead of split
to skip the empty string at the end of the iterator. Additionally, if you skip
迭代器的第一个元素,你得到你想要的结果:
let iterator = "aeiou".split_terminator("").skip(1);
println!("{:?}", iterator.collect::<Vec<_>>());
输出:
["a", "e", "i", "o", "u"]
闭包也可以作为 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()
}
我会使用 str::split
和空字符串,然后使用 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"],
);
}