【问题标题】:Get the Vec of owned values from a HashMap从 HashMap 中获取拥有值的 Vec
【发布时间】:2019-12-17 16:35:59
【问题描述】:

我编写的算法构建了一个临时的HashMap。完成后,我只对哈希图的values 感兴趣,因此我想将值的所有权从HashMap<K, V> 转移到Vec<V>

使用简化的哈希图示例:

fn main() {
    use std::collections::HashMap;
    let mut h: HashMap<_, _> = HashMap::new();
    h.insert(1, "foo".to_owned());
}

我能做到:

  • let vals: Vec&lt;&amp;String&gt; = h.values().collect(); - 简短而甜蜜,但 hashmap 仍然拥有这些值;
  • let vals: Vec&lt;String&gt; = h.values().cloned().collect()(如this question) - 结果是我需要的,但我被教导要避免额外的克隆;
  • let vals: Vec&lt;String&gt; = h.into_iter().map(|(_k, v)| v).collect(); - 无需克隆即可满足我的需求,但有点丑。

实际值是一个中等大小的结构体({String, Vec&lt;String&gt;},总共不到 KB)。

在这种情况下我应该默认避免clone 还是过早优化?有没有我想念的惯用方式来做到这一点?

【问题讨论】:

    标签: rust


    【解决方案1】:

    .into_iter().map(|(_, v)| v) 是惯用的做法。一点也不丑。

    如果你愿意,你可以这样做:

    use std::collections::hash_map;
    use std::collections::HashMap;
    use std::iter::{ExactSizeIterator, FusedIterator};
    
    struct IntoValues<K, V> {
        iter: hash_map::IntoIter<K, V>,
    }
    
    impl<K, V> IntoValues<K, V> {
        fn new(map: HashMap<K, V>) -> Self {
            Self {
                iter: map.into_iter(),
            }
        }
    }
    
    impl<K, V> Iterator for IntoValues<K, V> {
        type Item = V;
    
        fn next(&mut self) -> Option<Self::Item> {
            self.iter.next().map(|(_, v)| v)
        }
    
        fn size_hint(&self) -> (usize, Option<usize>) {
            self.iter.size_hint()
        }
    }
    impl<K, V> ExactSizeIterator for IntoValues<K, V> {}
    
    impl<K, V> FusedIterator for IntoValues<K, V> {}
    
    trait HashMapTool {
        type IntoValues;
        type Item;
        fn into_values(self) -> Self::IntoValues;
    }
    
    impl<K, V> HashMapTool for HashMap<K, V> {
        type Item = V;
        type IntoValues = IntoValues<K, V>;
        fn into_values(self) -> Self::IntoValues {
            IntoValues::new(self)
        }
    }
    
    fn main() {
        let mut h: HashMap<_, _> = HashMap::new();
        h.insert(1, "foo".to_owned());
    
        let _vals: Vec<_> = h.into_values().collect();
    }
    

    【讨论】:

    • 谢谢!很高兴看到我将如何实现 into_values(),但我想我会使用 into_iter().map() 来避免所有额外的代码。
    猜你喜欢
    • 1970-01-01
    • 2016-03-08
    • 2020-04-16
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多