Reputation: 33
I am trying to split up a bunch (50+) of json files, and to do so I want to classify their values by frequency depending on elements of the file name. Not only am I doing this but I am doing it as somewhat of a Rust newbie, because it wasn't fun enough to do in Python, for instance.
For the sake of the explanation, let's imagine files like these:
a-b-c-d.json
{
"var":"foo",
"array": [
'one',
'two'
]
}
b-c-d-f.json
{
"var":"bar",
"array": [
'one',
'three'
]
}
The data structure I want to end up with, after processing those two files, is something like this (note that this might very well be my first mistake):
{
'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
}
My pseudocode is more or less like this:
So, the type of the result variable would be HashMap<String, HashMap<String, HashMap<String, i8>>>
And the (actual) code in which I am getting errors is:
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;
}
The errors are:
<final_component_map[component]>.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>>>`
<final_component_map[component][element]>.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>>`
<final_component_map[component][element][value]> += 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>`
I would have thought that writing to Maps would be easier in Rust :D What exactly do I need to do to have my beautiful nested HashMap filled with the values?
Thanks a lot!
Upvotes: 2
Views: 1271
Reputation: 58825
Part of the point of the Entry
API is so that you can mutate the entry without having to look it up again. You can chain these lookups together like so:
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;
}
Upvotes: 3