Rust 如何合并流的迭代器?

Rust 如何合并流的迭代器?,rust,Rust,我正在写一个程序,从使用锈迹刮去链接。我正在使用hyper和futures 我收集了指向每个部分的链接,并使用stream::unfold构建对每个页面的访问: // Returns the links scraped, and probably Uri to the next page. fn process_body_and_return_next(body: Body) -> (Vec<String>, Option<Uri>) { ... } // In

我正在写一个程序,从使用锈迹刮去链接。我正在使用
hyper
futures

我收集了指向每个部分的链接,并使用
stream::unfold
构建对每个页面的访问:

// Returns the links scraped, and probably Uri to the next page.
fn process_body_and_return_next(body: Body) -> (Vec<String>, Option<Uri>) { ... }

// In main()
let mut core = Core::new().unwrap();
let handle = core.handle();
let client = Client::new(&handle);
let uris = ...

let jobs = uris.map(|uri| {
    stream::unfold(Some(uri), |uri| {
        uri.map(|uri| {
            client
                .get(uri)
                .and_then(|res| res.body().concat2())
                .map(process_body_and_return_next)
        })
    })
});

但这并不高效,因为我希望异步发送多个web请求。只要内部
准备就绪,组合的
就会产生值。

可以使用将迭代器转换为流,这允许您的流迭代器转换为流:

::futures::stream::iter_ok(jobs)
然后,您可以使用以下方法将此流平坦化为所有项目的单个流:


可以使用将迭代器转换为流,这允许您的流迭代器转换为流:

::futures::stream::iter_ok(jobs)
然后,您可以使用以下方法将此流平坦化为所有项目的单个流:

组合器获取两个
s,并在两个流中的一个准备就绪时生成

为了从两个以上的流中进行选择,您可以将调用链接到
select
。但是,由于您事先不知道必须选择打开的流的数量,因此必须将中间流框起来,以便删除特定的
类型,以便程序类型进行检查

extern crate futures;

use futures::Stream;

fn select_all<'a, I, T, E>(seq: I) -> Box<Stream<Item = T, Error = E> + 'a>
where
    I: IntoIterator,
    I::Item: Stream<Item = T, Error = E> + 'a,
    T: 'a,
    E: 'a,
{
    let mut iter = seq.into_iter();
    let mut result = Box::new(iter.next().expect("got an empty list of streams"))
        as Box<Stream<Item = T, Error = E>>;
    while let Some(next) = iter.next() {
        result = Box::new(result.select(next));
    }

    result
}
extern板条箱期货;
使用流;
fn选择所有
哪里
I:迭代器,
I::Item:Stream+'a,
T:a,
E:“a,
{
让mut iter=seq.into_iter();
让mut result=Box::new(iter.next().expect(“得到一个空的流列表”))
as盒;
而让一些(下一个)=iter.next(){
结果=框::新建(结果。选择(下一步));
}
后果
}
当然,有一种更有效的方法来实现这一点。有一个未来的组合,但还没有一个流。也许您可以自己实现它,并将其作为pull请求提交

组合器获取两个
s,并在两个流中的一个准备就绪时生成

为了从两个以上的流中进行选择,您可以将调用链接到
select
。但是,由于您事先不知道必须选择打开的流的数量,因此必须将中间流框起来,以便删除特定的
类型,以便程序类型进行检查

extern crate futures;

use futures::Stream;

fn select_all<'a, I, T, E>(seq: I) -> Box<Stream<Item = T, Error = E> + 'a>
where
    I: IntoIterator,
    I::Item: Stream<Item = T, Error = E> + 'a,
    T: 'a,
    E: 'a,
{
    let mut iter = seq.into_iter();
    let mut result = Box::new(iter.next().expect("got an empty list of streams"))
        as Box<Stream<Item = T, Error = E>>;
    while let Some(next) = iter.next() {
        result = Box::new(result.select(next));
    }

    result
}
extern板条箱期货;
使用流;
fn选择所有
哪里
I:迭代器,
I::Item:Stream+'a,
T:a,
E:“a,
{
让mut iter=seq.into_iter();
让mut result=Box::new(iter.next().expect(“得到一个空的流列表”))
as盒;
而让一些(下一个)=iter.next(){
结果=框::新建(结果。选择(下一步));
}
后果
}

当然,有一种更有效的方法来实现这一点。有一个未来的组合,但还没有一个流。也许您可以自己实现它,并将其作为pull请求提交

但通过这种方式,项目将逐个评估,而不是同时评估。是否有
版本的
期货(无序
)?@penguanwen您的要求不清楚。您需要由内部流生成的项目的
。如何“同时”交付任何内容?我需要一个无序的缓冲
。当您组合
Future
s的
Iterator
时,您可以使用
stream::futures\u ordered
stream::futures\u unordered
,如果您使用后者,只要
Future
中的一个可用,
流将产生值。当您有一个
未来
s时,您可以使用
流::流::缓冲区_无序
来实现这一点。但是在我的例子中,
s的
迭代器
很难以这种方式组合。我想不出原因。但是这样的话,这些项目将一个接一个地评估,而不是同时评估。是否有
版本的
期货(无序
)?@penguanwen您的要求不清楚。您需要由内部流生成的项目的
。如何“同时”交付任何内容?我需要一个无序的缓冲
。当您组合
Future
s的
Iterator
时,您可以使用
stream::futures\u ordered
stream::futures\u unordered
,如果您使用后者,只要
Future
中的一个可用,
流将产生值。当您有一个
未来
s时,您可以使用
流::流::缓冲区_无序
来实现这一点。但是在我的例子中,
s的
迭代器
很难以这种方式组合。我想不出原因。在futures 0.2(非稳定版本)中,似乎有一个针对streams的应用程序。它似乎是在不使用任何
框的情况下实现的。在futures 0.2(非稳定版本)中,似乎有一个for streams。它似乎是在不使用任何
Box
的情况下实现的。