简体   繁体   中英

Reduce an array of objects (of arrays of arrays), many levels of arrays

My array looks like this

const bookies = [
    {
      "name": "Bet365",
      "sports": [
        {
          "name": "Soccer",
          "leagues": [
            {
              "name": "Premier League",
              "country": "England"
            },
            {
              "name": "League One",
              "country": "England"
            },
            {
              "name": "League Two",
              "country": "England"
            }
          ]
        },
      ]
    },
    {
      "name": "ComeOn",
      "sports": [
        {
          "name": "Basketball",
          "leagues": [
            {
              "name": "NBA",
              "country": "USA"
            },
          ]
        }
      ]
    },
    {
      "name": "Bet365",
      "sports": [
        {
          "name": "Soccer",
          "leagues": [
            {
              "name": "Premier League",
              "country": "England"
            },
            {
              "name": "La Liga",
              "country": "Spain"
            },
            {
              "name": "League One",
              "country": "England"
            },
          ]
        },
      ]
    }
  ]

And I want it to be like this

const bookies = [
    {
      "name": "Bet365",
      "sports": [
        {
          "name": "Soccer",
          "leagues": [
            {
              "name": "Premier League",
              "country": "England"
            },
            {
              "name": "League One",
              "country": "England"
            },
            {
              "name": "League Two",
              "country": "England"
            },
            {
              "name": "La Liga",
              "country": "Spain"
            },
          ]
        },
      ]
    },
    {
      "name": "ComeOn",
      "sports": [
        {
          "name": "Basketball",
          "leagues": [
            {
              "name": "NBA",
              "country": "USA"
            },
          ]
        }
      ]
    }
  ]

It groups it by bookmaker name, and if there are multiple sports with same name, it looks inside and see if it is same league name and country, and if it is not, add league.

Here is my current code

const result = bookies.reduce((acc, d) => {
        const found = acc.find((a) => a.name === d.name)
        if (found) {
            d.sports.forEach((sport) => {
                if (!found.sports.some((item) => item.name === sport.name)) {
                    found.sports.push(sport)
                }
            })
        } else {
            acc.push({
                name: d.name,
                sports: d.sports,
            })
        }
        return acc
    }, [])

But I can't seem to figure out what to do next. Does anybody have some tips or can help me figure it out?

You could take an array of children keys and take the same callback for reduceing the arrays.

 const merge = level => (r, o) => { const key = children[level]; let temp = r.find(q => q.name === o.name); if (temp) { if (key) o[key].reduce(merge(level + 1), temp[key]); } else { r.push(o); } return r; }, children = ['sports', 'leagues'], data = [{ name: "Bet365", sports: [{ name: "Soccer", leagues: [{ name: "Premier League", country: "England" }, { name: "League One", country: "England" }, { name: "League Two", country: "England" }] }] }, { name: "ComeOn", sports: [{ name: "Basketball", leagues: [{ name: "NBA", country: "USA" }] }] }, { name: "Bet365", sports: [{ name: "Soccer", leagues: [{ name: "Premier League", country: "England" }, { name: "La Liga", country: "Spain" }, { name: "League One", country: "England" }] }] }], result = data.reduce(merge(0), []); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Try this

 const bookies = [ { "name": "Bet365", "sports": [ { "name": "Soccer", "leagues": [ { "name": "Premier League", "country": "England" }, { "name": "League One", "country": "England" }, { "name": "League Two", "country": "England" } ] }, ] }, { "name": "ComeOn", "sports": [ { "name": "Basketball", "leagues": [ { "name": "NBA", "country": "USA" }, ] } ] }, { "name": "Bet365", "sports": [ { "name": "Soccer", "leagues": [ { "name": "Premier League", "country": "England" }, { "name": "La Liga", "country": "Spain" }, { "name": "League One", "country": "England" }, ] }, ] } ] const result=bookies.reduce((acc,curr)=>{ if(acc[curr.name]){ const currLeagues=curr.sports[0].leagues; currLeagues.forEach(item=>{ if(.acc[curr.name].sports[0].leagues.find(league=> league.name === item.name)){ acc[curr.name].sports[0].leagues.push(item) } }) } else { acc[curr,name]=curr } return acc }.{}) console.log(result)
 .as-console-wrapper { max-height: 100%;important: top; 0; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM