1

Given the input array.

  let data = [
    {
      name: 'Name',
      countries: [
        {
          name: 'Country1',
          competitions: [
            {
              name: 'Competition1',
              matches: [
                { details: 'details' },
                { details: 'details' },
                { details: 'details' }
              ]
            },
            {
              name: 'Competition2',
              matches: [{ details: 'details' }]
            }
          ]
        },
        {
          name: 'Country2',
          competitions: [
            {
              name: 'Competition1',
              matches: [{ details: 'details' }]
            },
            {
              name: 'Competition2',
              matches: [{ details: 'details' }]
            },

            {
              name: 'Competition3',
              matches: [{ details: 'details' }, { detals: 'detail' }]
            }
          ]
        }
      ]
    },
    {
      name: 'Name2',
      countries: [
        {
          name: 'Country1',
          competitions: [
            {
              name: 'Competition1',
              matches: [{ details: 'details' }, { details: 'details' }]
            }
          ]
        }
      ]
    }
  ];

And desired output:

let sorted = [
    // For each Object in orginal array extract all matches and put it in new array.
    { name: 'Name', matches: [{}, {}, {}, {}, {}, {}, {}, {}] },
    { name: 'Name2', matches: [{}, {}] }
  ]

How can I transform data into sorted I can use nested 3 nested for loops and extract all matches into single array. But it does not give me desired output and I feel that nesting for loops is bad for resources and I'm certain that it can be done more concisely and after all I do not get expected output. I tried Object.assign creating new objects at starts etc etc.

Using for loop to get arr to store all matches from whole data array like so.

  for (var i = 0; i < data.length; i++) {
    for (var j = 0; j < data[i].countries.length; j++) {
      for (var l = 0; l < data[i].countries[j].competitions.length; l++) {
        for (
          var k = 0;
          k < data[i].countries[j].competitions[l].matches.length;
          k++
        ) {
          arr.push(data[i].countries[j].competitions[l].matches[k]);
        }
      }
    }

Is eyesore, and still leaves me with flat array of all matches which are no good.

Using ES6 and new goodies I manage to get closer to solution but leaves me with nested array of arrays that I can not seem to flatten.

  const d = data.map(i => {
    const inter = i.countries.map(e => e.competitions.map(z => z.matches));

    const final = inter.reduce((acc, next) => [...acc, ...next], []);

    return {
      name: i.name,
      matches: final
    };
  }) 

For educational purposes all solutions will be accepted no matter the performance at this point.

tl;dr How to transform data into sorted

4
  • Copying data gives me syntax error, can you fix it? Commented Mar 9, 2018 at 10:13
  • I shortened the next entry in array for readability. Just copy first item in array once more instead of second entry. Or better yet i will add another entry. Commented Mar 9, 2018 at 10:16
  • 1
    name: 'Name2' is inside countries array of Name1 is it correct? Commented Mar 9, 2018 at 10:17
  • @RahulSharma fixed the original data source my bad. Commented Mar 9, 2018 at 10:27

3 Answers 3

1
const sorted = data.map(o => {
  const name = o.name;
  let matches = [];
  o.countries.map(c => {
    return c.competitions.forEach(c => {
      c.matches.forEach(m => {
        matches.push(m);
      });
    });
  });
  return { name, matches };
});

Instead of using map, I created matches array, and while looping through every matches array from object, I'm just pushing the results into array. Here's a snippet:

let data = [
    {
      name: 'Name',
      countries: [
        {
          name: 'Country1',
          competitions: [
            {
              name: 'Competition1',
              matches: [
                { details: 'details' },
                { details: 'details' },
                { details: 'details' }
              ]
            },
            {
              name: 'Competition2',
              matches: [{ details: 'details' }]
            }
          ]
        },
        {
          name: 'Country2',
          competitions: [
            {
              name: 'Competition1',
              matches: [{ details: 'details' }]
            },
            {
              name: 'Competition2',
              matches: [{ details: 'details' }]
            },

            {
              name: 'Competition3',
              matches: [{ details: 'details' }, { detals: 'detail' }]
            }
          ]
        }
      ]
    }
  ];
const sorted = data.map(o => {
  const name = o.name;
  let matches = [];
  o.countries.map(c => {
    return c.competitions.forEach(c => {
      c.matches.forEach(m => {
        matches.push(m);
      });
    });
  });
  return { name, matches };
});
console.log(sorted);

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

3 Comments

Thanks I ended up with this one, because it does not use concat. Did not even cross my mind for a second to break out of map like that. You learn everyday.
I tried answering with map and then i remembered i had this problem once and came up with forEach and pushing into array. Next time you will remember it too, i guarantee! :)
Yeah I for sure will :D
1

You can to use reduce and just concat the matches

let result = data.map(v=>{
    let inter = v.countries.reduce((c,v)=> c.concat( v.competitions.map(z => z.matches).reduce((x,z) => x.concat( z ),[] ) ),[]);
    return {
        name : v.name,
        matches : inter
    }
});

Here is a snippet:

let data = [{
    name: 'Name',
    countries: [{
        name: 'Country1',
        competitions: [{
            name: 'Competition1',
            matches: [{
                details: 'details'
              },
              {
                details: 'details'
              },
              {
                details: 'details'
              }
            ]
          },
          {
            name: 'Competition2',
            matches: [{
              details: 'details'
            }]
          }
        ]
      },
      {
        name: 'Country2',
        competitions: [{
            name: 'Competition1',
            matches: [{
              details: 'details'
            }]
          },
          {
            name: 'Competition2',
            matches: [{
              details: 'details'
            }]
          },

          {
            name: 'Competition3',
            matches: [{
              details: 'details'
            }, {
              detals: 'detail'
            }]
          }
        ]
      },
    ]
  },
  {
    name: 'Name2',
    countries: [{
      name: 'Country1',
      competitions: [{
          name: 'Competition1',
          matches: [{
              details: 'details'
            },
            {
              details: 'details'
            },
            {
              details: 'details'
            }
          ]
        },
        {
          name: 'Competition2',
          matches: [{
            details: 'details'
          }]
        }
      ]
    }, ]
  }
];

let result = data.map(v => {
  let inter = v.countries.reduce((c, v) => c.concat(v.competitions.map(z => z.matches).reduce((x, z) => x.concat(z), [])), []);
  return {
    name: v.name,
    matches: inter
  }
});

console.log(result);

Comments

0

Might be easier to filter during parsing:

let sorted = [], last = [], json = '[{"name":"Name","countries":[{"name":"Country1","competitions":[{"name":"Competition1","matches":[{"details":"details1"},{"details":"details2"},{"details":"details3"}]},{"name":"Competition2","matches":[{"details":"details4"}]}]},{"name":"Country2","competitions":[{"name":"Competition1","matches":[{"details":"details5"}]},{"name":"Competition2","matches":[{"details":"details6"}]},{"name":"Competition3","matches":[{"details":"details7"},{"detals":"detail8"}]}]}]},{"name":"Name2","countries":[{"name":"Country1","competitions":[{"name":"Competition1","matches":[{"details":"details9"},{"details":"details10"}]}]}]}]'

JSON.parse(json, (k, v) => k === 'details' ? last.push(v) : 
  v.countries !== void 0 ? (sorted.push({ name: v.name, matches: last }), last = []) : 0)

console.log( sorted )

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.