0

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!

6
  • what if you have more than one year inside? Commented Feb 13, 2022 at 18:13
  • @NinaScholz for example, if there are more years inside team1, it should be like: { 'team1': [14697807552, 6858384], '2021': [...], '2020': [...] etc} Commented Feb 13, 2022 at 18:18
  • what happens with the children of the years? Commented Feb 13, 2022 at 18:21
  • @NinaScholz is it possible to have same property names inside an object? if not you can ignore year's children and return an object like this { team1: [...], 2021: [...], 2022: [...] } Commented Feb 13, 2022 at 18:25
  • Please note that a key like '2021' as an index, and so it will always be ordered before other properties in the object. Commented Feb 13, 2022 at 18:25

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I didn't know about property order for index tbh
0

I have found a bit different solution:) It is longer than answer from @trincot but also works

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]}]}]}];

const handleArr = (list, rez) => {
  list.forEach((item) => {
    rez[item.name] = item.metrics;
    item.children && handleArr(item.children, rez);
  });
};

const handle = (list) => {
  const rezArr = [];
  for (const item of list) {
    const rezObj = { [item.name]: item.metrics };
    item.children && handleArr(item.children, rezObj);
    rezArr.push(rezObj);
  }
  return rezArr;
};

console.log(handle(arr));

Comments

0

This approahc returns a different result and uses all previous information to get a denormalization of the data.

const
    flat = array => array.flatMap(({ name, metrics, children }) => children
        ? flat(children).map(q => ({ [name]: metrics, ...q }))
        : { [name]: metrics }),
    data = [{ 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] }] }] }],
    result = flat(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.