[英]How to use std::iter::Iterator::map for tree-like structures in Rust?
As I understand the idiomatic way to apply a function to each element of a structure in Rust, is to implement IntoIterator
and FromIterator
and use map
and collect
.据我了解,将函数应用于 Rust 结构的每个元素的惯用方法是实现
IntoIterator
和FromIterator
并使用map
和collect
。 Like this:像这样:
enum F<A> {
// fields omitted
}
impl<A> IntoIterator for F<A> {
// implementation omitted
}
impl<A> FromIterator<A> for F<A> {
// implementation omitted
}
fn mapF<A, B>(x : F<A>, f) -> F<B>
where f : Fn(A) -> B
{
x.into_iter().map(f).collect()
}
However it doesn't seem possible to implement FromIterator
for a tree, because there are multiple ways to organize a sequence of values into a tree.然而,似乎不可能为树实现
FromIterator
,因为有多种方法可以将一系列值组织到树中。 Is there some way around this?有没有办法解决这个问题?
the idiomatic way to apply a function to each element of a structure in Rust, is to implement
IntoIterator
andFromIterator
在 Rust
IntoIterator
函数应用于结构的每个元素的惯用方法是实现IntoIterator
和FromIterator
This is not quite true.这并不完全正确。 The idiomatic way is to provide one iterator, but you don't have to implement these traits.
惯用的方法是提供一个迭代器,但您不必实现这些特征。
Take for example &str
: there isn't a canonical way to iterate on a string.以
&str
为例:没有一种规范的方式来迭代字符串。 You could iterate on its bytes or its characters, therefore it doesn't implement IntoIterator
but has two methods bytes
and chars
returning a different type of iterator.你可以迭代它的字节或它的字符,因此它没有实现
IntoIterator
但有两个方法bytes
和chars
返回不同类型的迭代器。
A tree would be similar: there isn't a single way to iterate a tree, so it could have a depth_first_search
method returning a DepthFirstSearch
iterator and a breadth_first_search
method returning a BreadthFirstSearch
iterator.一棵树将是类似的:没有一种方法可以迭代一棵树,因此它可以有一个
depth_first_search
方法返回一个DepthFirstSearch
迭代器和一个breadth_first_search
方法返回一个BreadthFirstSearch
迭代器。
Similarly a String
can be constructed from an iterator of &str
or and iterator of char
so String
implements both FromIterator<&str>
and FromIterator<char>
, but it does not implement FromIterator<u8>
because random bytes are unlikely to form a valid UTF-8 string.类似地,
String
可以从&str
的迭代器或char
的迭代器构造,因此String
实现了FromIterator<&str>
和FromIterator<char>
,但它没有实现FromIterator<u8>
因为随机字节不太可能形成有效的 UTF- 8串。
That is, there isn't always a one-to-one relation between a collection, and its iterator.也就是说,集合与其迭代器之间并不总是一对一的关系。
and use […]
collect
并使用 […]
collect
This is (mostly) incorrect.这(大部分)是不正确的。 Collecting is not a good way to consume an iterator, unless you actually want to use the collected result afterwards.
收集不是使用迭代器的好方法,除非您真的想在之后使用收集的结果。 If you only want to execute the effect of an iterator, use
for
of the for_each
method.如果只想执行一个迭代器的效果,使用
for_each
方法的for
。
You could include information about tree structure into the iterator, something like您可以在迭代器中包含有关树结构的信息,例如
impl F {
pub fn path_iter(self) -> impl Iterator<Iter=(TreePath, A)> { ... }
// rest of impl
}
impl<A> FromIterator<(TreePath, A)> for F<A> {
// implementation omitted
}
fn mapF<A, B>(x : F<A>, f) -> F<B>
where f : Fn(A) -> B
{
x.path_iter().map(|pair| (pair.0, f(pair.1))).collect()
}
With TreePath
a type specific for your tree.使用
TreePath
特定于您的树的类型。 Probably better representing not the path itself but how to move to the next node.可能更好地表示不是路径本身而是如何移动到下一个节点。
I originally suggested implementing IntoIterator
with Item = (TreePath, A)
but on further thought the default iterator should still have Item = A
.我最初建议使用
Item = (TreePath, A)
实现IntoIterator
但进一步认为默认迭代器仍应具有Item = A
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.