为什么我不能反转str::split的结果?
Why can I not reverse the result of str::split?
根据 Split
的文档,在字符串上执行 split
的结果有一个 rev
方法:
fn main() {
let mut length = 0;
let mut mult = 1;
for part in "1:30".split(":").rev() {
length += mult * part.parse::<i32>().unwrap();
mult *= 60;
}
}
我收到以下错误:
error[E0277]: the trait bound `std::str::pattern::StrSearcher<'_, '_>: std::str::pattern::DoubleEndedSearcher<'_>` is not satisfied
--> src/main.rs:4:35
|
4 | for part in "1:30".split(":").rev() {
| ^^^ the trait `std::str::pattern::DoubleEndedSearcher<'_>` is not implemented for `std::str::pattern::StrSearcher<'_, '_>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::str::Split<'_, &str>`
error[E0277]: the trait bound `std::str::pattern::StrSearcher<'_, '_>: std::str::pattern::DoubleEndedSearcher<'_>` is not satisfied
--> src/main.rs:4:17
|
4 | for part in "1:30".split(":").rev() {
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::str::pattern::DoubleEndedSearcher<'_>` is not implemented for `std::str::pattern::StrSearcher<'_, '_>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::str::Split<'_, &str>`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Rev<std::str::Split<'_, &str>>`
问题是 rev()
仅当它实现 DoubleEndedIterator
时才在 Split
迭代器上定义,但 Split
仅在搜索者实现时才实现 DoubleEndedIterator
您要拆分的模式的满足 DoubleEndedSearcher
:
impl<'a, P> DoubleEndedIterator for Split<'a, P>
where
P: Pattern<'a>,
<P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,
文档列出了哪些类型实现了 DoubleEndedSearcher
。 None 的类型对应 &str
模式,所以当你拆分字符串时你不能使用 rev()
。
在你的特殊情况下,我想,将 split(":")
更改为 split(':')
就足够了(即拆分字符而不是字符串),因为字符模式搜索器 确实 实施 DoubleEndedSearcher
.
Rust 的这些特性(条件特征实现和方法局部特征边界)允许编写真正富有表现力的代码,但它们有时可能难以通读。
TLDR:StrSearcher
(搜索字符串模式的类型)没有实现 DoubleEndedSearcher
,因此,split
迭代器没有实现 DoubleEndedIterator
,因此,您不能对其调用 rev
。
如果您查看 rev
页面上的文档,您会看到 where Self: DoubleEndedIterator
。这意味着 rev
被定义 当且仅当 正在为 Iterator
特性实现的类型(即 Split
) 也实现了DoubleEndedIterator
特征。
如果你再往下看,你会看到:
impl<'a, P> DoubleEndedIterator for Split<'a, P>
where P: Pattern<'a>, P::Searcher: DoubleEndedSearcher<'a>
因此,DoubleEndedIterator
为 Split
实现当且仅当 这两个条件都满足时:P
必须是 Pattern
和它定义的 Searcher
类型必须实现 DoubleEndedSearcher
.
现在,您使用字符串文字作为模式,因此如果您检查 documentation for the str
type,您将看到:
impl<'a, 'b> Pattern<'a> for &'b str
其中,关联的 Searcher
类型定义为:
type Searcher = StrSearcher<'a, 'b>
快到了!按照 link 到 documentation for StrSearcher
和...
...DoubleEndedSearcher
没有实现。因此,所需的边界 不 满足并且 rev
不能用于 Split
迭代器。
其他答案都正确,但我想指出rsplit
。这可能更明显,性能更高。
那么,为什么不能使用 rev
?正如其他答案所述,它没有为 StrSearcher
实现。但是为什么没有实现呢?来自 DoubleEndedSearcher
文档:
For this, the impl of Searcher
and ReverseSearcher
need
to follow these conditions:
- All results of
next()
need to be identical
to the results of next_back()
in reverse order.
next()
and next_back()
need to behave as
the two ends of a range of values, that is they
can not "walk past each other".
使用字符串反转迭代器的问题是:
"baaab".split("aa") // -> ["b", "aa", "ab"];
但是,如果您从字符串的末尾开始,您会得到如下内容:
"baaab".split("aa").rev() // -> ["b", "aa", "ba"]
这明显不是同一套物品,顺序不同!
简而言之,您不能反转在字符串上拆分的迭代器,因为没有高效知道下一个时间的方法结果是。您必须将整个字符串拆分为一个集合,然后反转该集合!
这就是 rsplit
存在的原因 - 它意味着从字符串的末尾开始并以高效的方式拆分到开头。
根据 Split
的文档,在字符串上执行 split
的结果有一个 rev
方法:
fn main() {
let mut length = 0;
let mut mult = 1;
for part in "1:30".split(":").rev() {
length += mult * part.parse::<i32>().unwrap();
mult *= 60;
}
}
我收到以下错误:
error[E0277]: the trait bound `std::str::pattern::StrSearcher<'_, '_>: std::str::pattern::DoubleEndedSearcher<'_>` is not satisfied
--> src/main.rs:4:35
|
4 | for part in "1:30".split(":").rev() {
| ^^^ the trait `std::str::pattern::DoubleEndedSearcher<'_>` is not implemented for `std::str::pattern::StrSearcher<'_, '_>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::str::Split<'_, &str>`
error[E0277]: the trait bound `std::str::pattern::StrSearcher<'_, '_>: std::str::pattern::DoubleEndedSearcher<'_>` is not satisfied
--> src/main.rs:4:17
|
4 | for part in "1:30".split(":").rev() {
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::str::pattern::DoubleEndedSearcher<'_>` is not implemented for `std::str::pattern::StrSearcher<'_, '_>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::str::Split<'_, &str>`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Rev<std::str::Split<'_, &str>>`
问题是 rev()
仅当它实现 DoubleEndedIterator
时才在 Split
迭代器上定义,但 Split
仅在搜索者实现时才实现 DoubleEndedIterator
您要拆分的模式的满足 DoubleEndedSearcher
:
impl<'a, P> DoubleEndedIterator for Split<'a, P>
where
P: Pattern<'a>,
<P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,
文档列出了哪些类型实现了 DoubleEndedSearcher
。 None 的类型对应 &str
模式,所以当你拆分字符串时你不能使用 rev()
。
在你的特殊情况下,我想,将 split(":")
更改为 split(':')
就足够了(即拆分字符而不是字符串),因为字符模式搜索器 确实 实施 DoubleEndedSearcher
.
Rust 的这些特性(条件特征实现和方法局部特征边界)允许编写真正富有表现力的代码,但它们有时可能难以通读。
TLDR:StrSearcher
(搜索字符串模式的类型)没有实现 DoubleEndedSearcher
,因此,split
迭代器没有实现 DoubleEndedIterator
,因此,您不能对其调用 rev
。
如果您查看 rev
页面上的文档,您会看到 where Self: DoubleEndedIterator
。这意味着 rev
被定义 当且仅当 正在为 Iterator
特性实现的类型(即 Split
) 也实现了DoubleEndedIterator
特征。
如果你再往下看,你会看到:
impl<'a, P> DoubleEndedIterator for Split<'a, P>
where P: Pattern<'a>, P::Searcher: DoubleEndedSearcher<'a>
因此,DoubleEndedIterator
为 Split
实现当且仅当 这两个条件都满足时:P
必须是 Pattern
和它定义的 Searcher
类型必须实现 DoubleEndedSearcher
.
现在,您使用字符串文字作为模式,因此如果您检查 documentation for the str
type,您将看到:
impl<'a, 'b> Pattern<'a> for &'b str
其中,关联的 Searcher
类型定义为:
type Searcher = StrSearcher<'a, 'b>
快到了!按照 link 到 documentation for StrSearcher
和...
...DoubleEndedSearcher
没有实现。因此,所需的边界 不 满足并且 rev
不能用于 Split
迭代器。
其他答案都正确,但我想指出rsplit
。这可能更明显,性能更高。
那么,为什么不能使用 rev
?正如其他答案所述,它没有为 StrSearcher
实现。但是为什么没有实现呢?来自 DoubleEndedSearcher
文档:
For this, the impl of
Searcher
andReverseSearcher
need to follow these conditions:
- All results of
next()
need to be identical to the results ofnext_back()
in reverse order.next()
andnext_back()
need to behave as the two ends of a range of values, that is they can not "walk past each other".
使用字符串反转迭代器的问题是:
"baaab".split("aa") // -> ["b", "aa", "ab"];
但是,如果您从字符串的末尾开始,您会得到如下内容:
"baaab".split("aa").rev() // -> ["b", "aa", "ba"]
这明显不是同一套物品,顺序不同!
简而言之,您不能反转在字符串上拆分的迭代器,因为没有高效知道下一个时间的方法结果是。您必须将整个字符串拆分为一个集合,然后反转该集合!
这就是 rsplit
存在的原因 - 它意味着从字符串的末尾开始并以高效的方式拆分到开头。