在Rust中向vector的每个元素添加一个新键

时间:2017-10-15 03:37:57

标签: rust

我有一个结构向量。我想为每个元素添加一个额外的字段。最好的方法是什么?

这样的事情:

// Pseudo code

let items = vec![elem1, elem2, elem3, elem4];
for x in items {
    // Something like this
    x["some_additional_key"] = get_data(x);
} 

//
// Now I have items[i].some_additional_key in each element

1 个答案:

答案 0 :(得分:4)

Rust是statically-typed language;您可能熟悉其他类似的语言,如C ++,Java或Swift。在这些语言中,编译程序时,结构的成员,类型和布局是固定的。

正因为如此,没办法在运行时添加新的结构字段 - 没有" ifs"," ands",或者"的击打" - 你不能这样做。

相反,你必须以其他方式对动态性质进行建模:

  1. 使用允许任意扩展的类型。 HashMapBTreeMap(以及许多其他类似类型)允许您拥有任意数量的键值对。在幕后,这基本上是有多少动态语言工作 - 将字符串映射到任意值:

    use std::collections::HashMap;
    
    #[derive(Debug, Default)]
    struct Element(HashMap<String, u8>);
    
    fn get_data(_: &Element) -> u8 {
        42
    }
    
    fn main() {
        let mut items = vec![
            Element::default(),
            Element::default(),
            Element::default(),
            Element::default(),
        ];
    
        for x in &mut items {
            let value = get_data(x);
            x.0
                .entry("some_additional_key".to_string())
                .or_insert(value);
        }
    }
    
  2. 使用允许特定扩展的类型。 Option允许存在或不存在值:

    #[derive(Debug, Default)]
    struct Element {
        some_additional_key: Option<u8>,
    }
    
    fn get_data(_: &Element) -> u8 {
        42
    }
    
    fn main() {
        let mut items = vec![
            Element::default(),
            Element::default(),
            Element::default(),
            Element::default(),
        ];
    
        for x in &mut items {
            let value = get_data(x);
            x.some_additional_key = Some(value);
        }
    }
    
  3. 使用构图。创建一个包装现有类型的新类型:

    #[derive(Debug, Default)]
    struct Element;
    
    #[derive(Debug)]
    struct EnhancedElement {
        element: Element,
        some_additional_key: u8,
    }
    
    fn get_data(_: &Element) -> u8 {
        42
    }
    
    fn main() {
        let items = vec![
            Element::default(),
            Element::default(),
            Element::default(),
            Element::default(),
        ];
    
        let enhanced: Vec<_> = items
            .into_iter()
            .map(|element| {
                let some_additional_key = get_data(&element);
                EnhancedElement {
                    element,
                    some_additional_key,
                }
            })
            .collect();
    }
    
  4. 另见: