将切片过滤为矢量

时间:2016-06-14 00:59:15

标签: rust

我有一个结构:

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不满意。

那么,这样做的正确方法是什么?我应该采取除切片以外的其他方式吗?

1 个答案:

答案 0 :(得分:2)

  

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<T>可以作为&[T]运行,所以这不是真正的问题。包含的类型是问题:您有一个Vec<&Foo>的集合,但需要传递&[Foo]

逻辑上,错误是有道理的。你的函数需要一大块代表{strong>连续范围Foo的内存,但这不是你拥有的。通过过滤,您可以获得非连续数据。此外,您还创建了一系列指向实际数据的指针。

你如何解决?

  1. 如果您控制another_func,则可以将其更改为&[&Foo]
  2. 您可以将其更改为更通用的

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