'Transform array of Strings into Object
Given the following values:
const values = ['name1|engine1|color1', 'name2|engine2|color2', 'name3|engine3|color3']
I would like to create an array for the values of the same position, like this:
cars = {
names: ['name1', 'name2', 'name3'],
engines: ['engine1', 'engine2', 'engine3'],
colors: ['color1', 'color2', 'color3'],
...other properties
}
I tried to do it this way:
values.reduce((acc, value) => {
const [name, engine, color] = value.split('|')
acc.names.push(name)
acc.engines.push(engine)
acc.colors.push(color)
return acc
}, {})
The problem is that acc.name, acc.engine and acc.color don't exist yet, and it gives an error on push. What would be a way to do this cleanly, taking into account that they will have other properties?
Solution 1:[1]
- Case1.
const values = [
"name1|engine1|color1",
"name2|engine2|color2",
"name3|engine3|color3"
];
const cars = {
names: [],
engines: [],
colors: []
};
const result = values.reduce((acc, value) => {
const [name, engine, color] = value.split("|");
acc.names.push(name);
acc.engines.push(engine);
acc.colors.push(color);
return acc;
}, cars);
console.log(result);
- Case2.
const values = [
"name1|engine1|color1",
"name2|engine2|color2",
"name3|engine3|color3"
];
const result = values.reduce((acc, value) => {
const [name, engine, color] = value.split("|");
(acc.names ??= []).push(name);
(acc.engines ??= []).push(engine);
(acc.colors ??= []).push(color);
return acc;
}, {});
console.log(result);
Solution 2:[2]
If you have a very long property names, you can also do this:
const values = [
"name1|engine1|color1",
"name2|engine2|color2",
"name3|engine3|color3"
];
const keys = ["names", "engines", "colors", ...];
const results = values.reduce((acc, value) => {
const segments = value.split("|");
keys.forEach((key, index) => {
(acc[key] ??= []).push(segments[index]);
});
return acc;
}, {});
console.log(results)
Solution 3:[3]
Object.fromEntries makes this easy to do this in a simple map call:
const reconstruct = (names, values) =>
values .map (v => Object .fromEntries (v .split ('|') .map ((v, i) => ([names[i], v]))))
console .log (reconstruct (
['name', 'engine', 'color'], [
'name1|engine1|color1',
'name2|engine2|color2',
'name3|engine3|color3'
]))
.as-console-wrapper {max-height: 100% !important; top: 0}
We convert each of our strings into something like [['name', 'name1'], ['engine', 'engine1'], ['color', 'color1']] then call Object.fromEntries on that.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dali |
| Solution 2 | zzz |
| Solution 3 | Scott Sauyet |
