【问题标题】:Filter a slice into a vector将切片过滤成向量
【发布时间】:2016-06-14 10:24:29
【问题描述】:

我有一个结构:

enum Bar {
    Bar0,
    Bar1,
    Bar2
}

struct Foo {
    bar: Bar 
}

我有一个函数需要一片 Foos:

fn do_the_thing(foos: &[Foo]) { ... }

需要做的部分事情是在切片的所有“bar”值相同的元素上调用另一个函数:

fn another_func(foos: &[Foo]) { ... }

我尝试过这样的事情:

fn do_the_thing(foos: &[Foo]) { 
    let bar0_foos = foos.iter().filter(|f| f.bar == Bar0 );

    another_func(&bar0_foos);
}

不幸的是,有人告诉我 bar0_foos 是&std::iter::Filter<std::slice::Iter<...>>。我也试过:

fn do_the_thing(foos: &[Foo]) { 
    let bar0_foos = foos.iter().filter(|f| f.bar == Bar0 ).collect();

    another_func(&bar0_foos);
}

在这里,我被告知std::marker::Sized 不满意。

那么,这样做的正确方法是什么?我应该吃片以外的东西吗?

【问题讨论】:

    标签: rust


    【解决方案1】:

    std::marker::Sized 不满意。

    由于Iterator::collect 返回一个泛型类型,编译器使用类型推断来确定该类型必须是什么。在这种情况下,您将对bar0_foos 的引用传递给接受&[Foo] 的函数。通过推断,这意味着bar0_foos 必须是[Foo] 类型。

    由于[Foo] 是一个未调整大小的类型,因此您无法创建该类型的值。

    通常,您指定要收集到的集合类型:

    let bar0_foos: Vec<_> = // ...
    

    提供此错误:

    error: mismatched types:
     expected `&[Foo]`,
        found `&collections::vec::Vec<&Foo>`
    (expected slice,
        found struct `collections::vec::Vec`) [E0308]
    <anon>:10     another_func(&bar0_foos);
                               ^~~~~~~~~~
    

    这里的错误消息有点误导,因为Vec&lt;T&gt; 可以作为&amp;[T] 运行,所以这不是真正的问题。包含的类型是问题所在:您有一个Vec&lt;&amp;Foo&gt; 的集合,但需要传递一个&amp;[Foo]

    从逻辑上讲,这个错误是有道理的。您的函数需要一大块内存,它代表Foo连续 范围,但这不是您所拥有的。通过过滤,您有可能获得不连续的数据。此外,您还创建了一系列指向真实数据的指针。

    你是怎么解决的?

    1. 如果您控制another_func,您可以将其更改为接收&amp;[&amp;Foo]
    2. 你可以把它改成更通用的

      fn another_func<F>(foos: &[F]) 
          where F: Borrow<Foo>
      
    3. 您可以复制/克隆这些值并创建一个新向量。然后你会得到一个Vec&lt;Foo&gt;,它可以作为&amp;[Foo]传入。
    4. 您可以重新排序输入切片以将所有适当的Foos 放在一起,然后获取子切片。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      相关资源
      最近更新 更多