创建一个Vec <btreeset <char>&gt;来自Vec <vec <char>&gt;

时间:2015-12-12 20:17:39

标签: collections functional-programming rust

我正在尝试从Vec<BTreeSet<char>>创建一个集合(Vec<Vec<char>>)的向量。到目前为止,这是我的进展:

use std::collections::BTreeSet;

fn main() {
    // The data
    let transaction_list = [
        vec!['A','B','C','D'],
        vec!['B','B','C'],
        vec!['A','B','B','D']
    ];

    // Successfully created a set from the Vec of Vec. It contains unique chars
    let item_set: BTreeSet<char> = transaction_list.iter().flat_map(|t| t).cloned().collect();

    // Made the same Vec of Vec. Basically just experimenting with map and collect
    let the_same_transaction_list: Vec<Vec<char>> = transaction_list.iter().map(|t| t ).cloned().collect::<Vec<_>>();

    // ERROR
    let transaction_set: Vec<BTreeSet<char>> = transaction_list
                                                .iter()
                                                .map(|t| t.iter().map(|t| t).cloned().collect() )
                                                .cloned().collect::<Vec<_>>();
}

错误消息是:

error: the trait `core::iter::FromIterator<char>` is not implemented for the type `&_` [E0277]
                                      .map(|t| t.iter().map(|t| t).cloned().collect() )
                                                                            ^~~~~~~~~
help: see the detailed explanation for E0277
note: a collection of type `&_` cannot be built from an iterator over elements of type `char`

我没有找到从Vec<BTreeSet<char>>中制作Vec<Vec<char>>的正确方法。这是游乐场网址:http://is.gd/WVONHY

1 个答案:

答案 0 :(得分:4)

错误消息有点奇怪。这是解决方案:

let transaction_set: Vec<BTreeSet<_>> =
    transaction_list
    .iter()
    .map(|t| t.iter().cloned().collect())
    .collect();

两个主要变化是:

  1. map(|x| x)毫无意义。这是一个无操作。
  2. 我删除了外clonedmap调用的结果类型已经是BTreeSet。没有必要再次克隆它。
  3. 后者修复了你的问题,让我们来看看定义:

    fn cloned<'a, T>(self) -> Cloned<Self> 
        where Self: Iterator<Item=&'a T>,
              T: 'a + Clone
    

    为了能够调用cloned,迭代器Item必须是引用才能克隆。但是,您试图迭代BTreeSet s,这不是引用。编译器选择告诉您,collect char的内部迭代器&_无法进入cloned(对某种类型的引用),这样就可以满足调用{{}的要求。 1}}。我的猜测是内部类型比collect所需的类型具有更多的摆动空间。如果我们重写一下原始代码,在内部有一个更确定的类型:

    let transaction_set: Vec<_> =
        transaction_list
        .iter()
        .map(|t| -> BTreeSet<_> {t.iter().cloned().collect()})
        .cloned().collect();
    

    我们得到一组不同的错误:

    error: type mismatch resolving `<[closure...] as core::ops::FnOnce<(&collections::vec::Vec<char>,)>>::Output == &_`:
     expected struct `collections::btree::set::BTreeSet`,
        found &-ptr [E0271]
             .cloned().collect();
              ^~~~~~~~
    
    error: no method named `collect` found for type `core::iter::Cloned<core::iter::Map<core::slice::Iter<'_, collections::vec::Vec<char>>, [closure...]>>` in the current scope
             .cloned().collect();
                       ^~~~~~~~~
    note: the method `collect` exists but the following trait bounds were not satisfied: `core::iter::Cloned<core::iter::Map<core::slice::Iter<'_, collections::vec::Vec<char>>, [closure...]>> : core::iter::Iterator`
    

    这有助于强调问题源于cloned的外部使用。