Skip to content
Advertisement

build array of object from tree object

I’m trying to get into javascript’s built-in reduce function and with the help of that build objects inside array. But you can use whatever function or method you want.

Expected output

[
  { 'team1': [14697807552, 6858384], '2021': [14697807552, 6858384], 'pepsi': [null, null], 'cola': [14697807552, 6858384] },
  { 'team2': [10268029152, 6922128], '2021': [10268029152, 6922128], 'pepsi': [null, 4800], 'cola': [10268029152, 6917328] },
]

What I tried to do

I created a function which takes array as an argument and calls reduce for each array’s element.

function transform(arr, obj = {}) {
  return arr.reduce((acc, item) => {
    const newObj = {};
    newObj[item.name] = item.metrics;
    acc.push(newObj);

    if (item.children) {
      transform(item.children, newObj);
    }

    return acc;
  }, []);
}
console.log(transform(arr))
<script>
  const arr = [{
      "name": "team1",
      "metrics": [
        14697807552,
        6858384
      ],
      "children": [{
        "name": "2021",
        "metrics": [
          14697807552,
          6858384
        ],
        "children": [{
            "name": "pepsi",
            "metrics": [
              null,
              null
            ]
          },
          {
            "name": "cola",
            "metrics": [
              14697807552,
              6858384
            ]
          }
        ]
      }]
    },
    {
      "name": "team2",
      "metrics": [
        10268029152,
        6922128
      ],
      "children": [{
        "name": "2021",
        "metrics": [
          10268029152,
          6922128
        ],
        "children": [{
            "name": "pepsi",
            "metrics": [
              null,
              4800
            ]
          },
          {
            "name": "cola",
            "metrics": [
              10268029152,
              6917328
            ]
          }
        ]
      }]
    }
  ]
</script>

But it gives me output that I don’t want:

[
  { team1: [ 14697807552, 6858384 ] },
  { team2: [ 10268029152, 6922128 ] }
]

If you didn’t understand my question or you have question, ask me. Thanks for paying attention!

Answer

The transform function doesn’t do anything with the second argument obj, and so when you call transform recursively, newObj is not extended: this makes the recursive call losing any desired effect.

Instead of passing that second argument, you could use Object.assign to collect all objects that come back from recursion, and so merge them into one object:

const convert = arr =>
    arr?.map(({name, metrics, children}) => 
        Object.assign({[name]: metrics}, ...convert(children))) ?? [];

const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];

console.log(convert(arr));

Please realise that a property like ‘2021’ is an index and will be ordered before other, non-index properties. Even if you print an object like { 'a': 2, '2021': 1 } you’ll get the keys in opposite order for that same reason.

If the order of the object keys is important to you, then you should go for an array of pairs in stead of a plain object. Arrays are the structure of choice when you need order, and plain objects should be used when order is not essential.

Advertisement