简体   繁体   English

如何在 Rust 中将 std::iter::Iterator::map 用于树状结构?

[英]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 结构的每个元素的惯用方法是实现IntoIteratorFromIterator并使用mapcollect 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 and FromIterator在 Rust IntoIterator函数应用于结构的每个元素的惯用方法是实现IntoIteratorFromIterator

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但有两个方法byteschars返回不同类型的迭代器。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM