'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