【问题标题】:Rust - How to add data to a triply nested HashMapRust - 如何将数据添加到三重嵌套的 HashMap
【发布时间】:2021-06-21 08:17:20
【问题描述】:

我正在尝试拆分一堆 (50+) json 文件,为此我想根据文件名的元素按频率对它们的值进行分类。我不仅在做这件事,而且在做这件事时有点像 Rust 新手,因为例如在 Python 中做这件事就不够有趣。

为了便于解释,让我们想象一下这样的文件:

a-b-c-d.json
{
    "var":"foo",
    "array": [
        'one',
        'two'
    ]
}
b-c-d-f.json
{
    "var":"bar",
    "array": [
        'one',
        'three'
    ]
}

在处理完这两个文件后,我想要最终得到的数据结构是这样的(请注意,这很可能是我的第一个错误):

{
  'a' : {
    'var' : { 
      'foo': 1
    }, 'array' : {
      'one': 1, 'two': 1 
    }
  },
  'b' : {
    'var' : { 
      'foo': 1,
      'bar': 1
    }, 'array' : {
      'one': 2, 'two': 1, 'three': 1
    }
  }
(also 'c', 'd' and 'f') - I hope the intention is clear with this small example
}

我的伪代码或多或少是这样的:

  1. 对于每个 json 文件
  2. 用'-'将名称分成几部分
  3. 对于 json 文件中的每个元素(键:值)
  4. 将其添加到 result[part][key][value] 作为出现次数

因此,结果变量的类型将是HashMap<String, HashMap<String, HashMap<String, i8>>>

我遇到错误的(实际)代码是:

type ComponentValueElement = HashMap<String, i8>;
type ComponentElement = HashMap<String, ComponentValueElement>;
type ComponentMap = HashMap<String, ComponentElement>;
(...)
fn increase_ocurrence_of_element_in_configuration(component: &String, element: &String, value: &String, final_component_map: &mut ComponentMap) {
    final_component_map.entry(component.into()).or_insert( HashMap::new() );
    final_component_map[component].entry(element.into()).or_insert(HashMap::new());
    final_component_map[component][element].entry(value.into()).or_insert(0);

    final_component_map[component][element][value] += 1;
}

错误是:

&lt;final_component_map[component]&gt;.entry(element.into()).or_insert(HashMap::new());

cannot borrow data in an index of `std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, i8>>>` as mutable

cannot borrow as mutable

help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, i8>>>`

&lt;final_component_map[component][element]&gt;.entry(value.into()).or_insert(0);

cannot borrow data in an index of `std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, i8>>` as mutable

cannot borrow as mutable

help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<std::string::String, std::collections::HashMap<std::string::String, i8>>`

&lt;final_component_map[component][element][value]&gt; += 1;

cannot assign to data in an index of `std::collections::HashMap<std::string::String, i8>`

cannot assign

help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<std::string::String, i8>`

我原以为在 Rust 中写入 Maps 会更容易:D 我到底需要做什么才能让我漂亮的嵌套 HashMap 填充这些值?

非常感谢!

【问题讨论】:

  • 使用 HashMap&lt;(String, String, String), i8&gt; 类型的单个 hashmap 可能会更有效。
  • 这是……那是一回事吗? :D 我将如何添加东西呢?入口界面会一样吗?另一个问题可能首先是地图的初始化,因为我遍历了所有 json 文件,拆分并创建了 HashMap 的第一层(也通过 .entry().or_insert()
  • 这样的事情是否可行取决于您想要支持哪种访问模式。例如,如果您想遍历所有 map[a],您可能需要使用嵌套映射。
  • 是的,有不同的优点和缺点。例如,使用扁平结构,删除整个分支会更慢。
  • 我现在真的不需要对此进行迭代,我只想要一份报告,以便我可以拆分文件。为此,至少在我看来,初始设置效果更好。但是知道你可以用元组做 HashMaps——我以前没有想到——这本身就很有价值。谢谢@PeterHall!

标签: collections rust hashmap


【解决方案1】:

Entry API 的部分意义在于,您可以更改条目而无需再次查找。您可以像这样将这些查找链接在一起:

fn increase_ocurrence_of_element_in_configuration(
    component: &str,
    element: &str,
    value: &str,
    final_component_map: &mut ComponentMap,
) {
    *final_component_map
        .entry(component.into())
        .or_default()
        .entry(element.into())
        .or_default()
        .entry(value.into())
        .or_default() += 1;
}

【讨论】:

  • 这就像entry() API 的电视广告。 :) 你可以使用or_default() 而不是or_insert(HashMap::new()) 让它更短。 (可能也更快,因为or_default() 等价于or_insert_with(|| HashMap::default()),所以它只在条目为空时调用HashMap::new()。OTOH or_insert(HashMap::new()) 总是创建空哈希图并依赖优化器来优化创建,这可能或者可能不会发生,具体取决于优化器。)
  • @user4815162342 已更新。这样好多了。
  • 谢谢两位,确实解决了问题!!
猜你喜欢
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 2019-02-11
相关资源
最近更新 更多