I am relatively new to Javascript. I am struggling with data wrangling. I would like to avoid loops.
I need to keep the higher levels of structure of "data_1", but insert an object in place of each of the key values of the form {name: "Key n", length: int}
The objects have of the following structures:
const data_1 = {
Category1: ["Key A", "Key B", "Key C"],
Category2: ["Key D", "Key E", "Key F"],
Category3: ["Key G", "Key H"]
}
const data_2 = {
"Key A": 100,
"Key B": 200,
"Key C": 300,
"Key D": 400,
"Key E": 400,
"Key F": 300,
"Key G": 200,
"Key H": 100
}
The target structure should be:
result = {
Category1: [{name:"Key A", length:100}, {name:"Key B", length:200}, {name: "Key C", length:300}],
Category2: [{name:"Key D", length:400}, {name:"Key E", length:400}, {name: "Key F", length:300}],
Category3: [{name:"Key G", length:200}, {name:"Key H", length:100}]
}
I suspect the way to tackle this is something akin to the following pseudo code. I am struggling to define an object as [name: key, length:data_2.key] .
let results = Object.fromEntries(data_1.map(key => [name: key, length:data_2.key]));
Any and all help is appreciated :)
CodePudding user response:
A reduce will do the trick and be quite readable too
const result = Object.entries(data_1).reduce((acc, [key, vals]) => {
acc[key] = vals.map(val => ({ name: val,length: data_2[val] }));
return acc;
}, {});
console.log(result);
<script>
const data_1 = {
Category1: ["Key A", "Key B", "Key C"],
Category2: ["Key D", "Key E", "Key F"],
Category3: ["Key G", "Key H"]
}
const data_2 = {
"Key A": 100,
"Key B": 200,
"Key C": 300,
"Key D": 400,
"Key E": 400,
"Key F": 300,
"Key G": 200,
"Key H": 100
}</script>
CodePudding user response:
- Using
Object#entries
, get list of key-value pairs fromdata_1
- Using
Array#reduce
, iterate over the above while updating the resulting object- In each iteration, add the new pair where the value is the list of objects having
name
andlength
generated usingArray#map
. We use thespread operator
(...acc
) to preserve existing accumulated pairs in every iteration.
- In each iteration, add the new pair where the value is the list of objects having
const
data_1 = { Category1: ["Key A", "Key B", "Key C"], Category2: ["Key D", "Key E", "Key F"], Category3: ["Key G", "Key H"] },
data_2 = { 'Key A': 100, 'Key B': 200, 'Key C': 300, 'Key D': 400, 'Key E': 400, 'Key F': 300, 'Key G': 200, 'Key H': 100 };
const result = Object.entries(data_1).reduce((acc, [key, names]) => ({
...acc,
[key]: names.map(name => ({ name, length: data_2[name] }))
}), {});
console.log(result);
CodePudding user response:
If we grab the entries, we can map over the keys and get each of them like this. Then we can create an object from the transformed entries.
const data_1 = {
Category1: ["Key A", "Key B", "Key C"],
Category2: ["Key D", "Key E", "Key F"],
Category3: ["Key G", "Key H"]
};
const data_2 = {
"Key A": 100,
"Key B": 200,
"Key C": 300,
"Key D": 400,
"Key E": 400,
"Key F": 300,
"Key G": 200,
"Key H": 100
};
const data_3 = Object.fromEntries(
Object.entries(data_1)
.map(([cat, keys]) => [cat, keys.map((key) => ({ name: key, length: data_2[key] }))]
)
);
console.log(data_3);
CodePudding user response:
You can do something like this:
const result = {};
Object.keys(data_1).forEach((key) => {
const item = data_1[key];
result[key] = item.map((key) => {
return { name: key, length: data_2[key] };
});
});
Either way, seems a bit convoluted to use objects in that manner, when you could maybe use arrays for the data format.
Here's a snippet with a working example:
const data_1 = {
Category1: ['Key A', 'Key B', 'Key C'],
Category2: ['Key D', 'Key E', 'Key F'],
Category3: ['Key G', 'Key H'],
};
const data_2 = {
'Key A': 100,
'Key B': 200,
'Key C': 300,
'Key D': 400,
'Key E': 400,
'Key F': 300,
'Key G': 200,
'Key H': 100,
};
const result = {};
Object.keys(data_1).forEach((key) => {
const item = data_1[key];
result[key] = item.map((key) => {
return { name: key, length: data_2[key] };
});
});
console.log(result);