Remove duplicate objects from an array but merge nested objects

陌路散爱 提交于 2021-01-27 10:54:53

问题


Currently have an array of objects which contain game releases. However game releases can happen on multiple platforms and these appear as separate objects within the array. I'm looking to remove duplicate games by comparing the game id but merge the platforms object

I have tried using the reduce function which successfully removes duplicate objects by game id but I'm unable to adapt this to merge platforms

const filteredArr = data.reduce((acc, current) => {
  const x = acc.find(item => item.game.id === current.game.id);

  if (!x) {
    return acc.concat([current]);
  } else {
    return acc;
  }
}, []);

Current Array:

const data = [{
  "id": 157283,
  "date": 1553212800,
  "game": {
    "id": 76882,
    "name": "Sekiro: Shadows Die Twice",
    "popularity": 41.39190295640344
  },
  "human": "2019-Mar-22",
  "m": 3,
  "platform": {"id": 48, "name": "PlayStation 4"},
  "region": 8,
  "y": 2019
}, {
  "id": 12,
  "date": 1553212800,
  "game": {
    "id": 76832,
    "name": "Spiderman",
    "popularity": 41.39190295640344
  },
  "human": "2019-Mar-22",
  "m": 3,
  "platform": {"id": 6, "name": "PC (Microsoft Windows)"},
  "region": 8,
  "y": 2019
}, {
  "id": 157283,
  "date": 1553212800,
  "game": {
    "id": 76882,
    "name": "Sekiro: Shadows Die Twice",
    "popularity": 41.39190295640344
  },
  "human": "2019-Mar-22",
  "m": 3,
  "platform": {"id": 48, "name": "Xbox"},
  "region": 8,
  "y": 2019
}]

Expected format after merge:

[{
  "id": 157283,
  "date": 1553212800,
  "game": {
    "id": 76882,
    "name": "Sekiro: Shadows Die Twice",
    "popularity": 41.39190295640344
  },
  "human": "2019-Mar-22",
  "m": 3,
  "platforms": ["PlayStation", "Xbox"],
  "region": 8,
  "y": 2019
}, {
  "id": 12,
  "date": 1553212800,
  "game": {
    "id": 76832,
    "name": "Spiderman",
    "popularity": 41.39190295640344
  },
  "human": "2019-Mar-22",
  "m": 3,
  "platforms": ["Playstation"],
  "region": 8,
  "y": 2019
}]

回答1:


You were really close, you just need to change the logic a bit. You can try something like the following; an example - https://repl.it/@EQuimper/ScaryBumpyCircle

const filteredArr = data.reduce((acc, current) => {
  const x = acc.find(item => item.game.id === current.game.id);

  if (!x) {
    current.platform = [current.platform]
    acc.push(current);
  } else {
    x.platform.push(current.platform);
  }

  return acc;
}, []);

The return value is

[
  {
    "id": 157283,
    "date": 1553212800,
    "game": {
      "id": 76882,
      "name": "Sekiro: Shadows Die Twice",
      "popularity": 41.39190295640344
    },
    "human": "2019-Mar-22",
    "m": 3,
    "platform": [
      {
        "id": 48,
        "name": "PlayStation 4"
      },
      {
        "id": 48,
        "name": "Xbox"
      }
    ],
    "region": 8,
    "y": 2019
  },
  {
    "id": 12,
    "date": 1553212800,
    "game": {
      "id": 76832,
      "name": "Spiderman",
      "popularity": 41.39190295640344
    },
    "human": "2019-Mar-22",
    "m": 3,
    "platform": [
      {
        "id": 6,
        "name": "PC (Microsoft Windows)"
      }
    ],
    "region": 8,
    "y": 2019
  }
]

If you want to have just an array of platform strings, go with

const filteredArr = data.reduce((acc, current) => {
  const x = acc.find(item => item.game.id === current.game.id);

  if (!x) {
    current.platform = [current.platform.name]
    acc.push(current);
  } else {
    x.platform.push(current.platform.name);
  }

  return acc;
}, []);

And now the return value is

[
  {
    "id": 157283,
    "date": 1553212800,
    "game": {
      "id": 76882,
      "name": "Sekiro: Shadows Die Twice",
      "popularity": 41.39190295640344
    },
    "human": "2019-Mar-22",
    "m": 3,
    "platform": [
      "PlayStation 4",
      "Xbox"
    ],
    "region": 8,
    "y": 2019
  },
  {
    "id": 12,
    "date": 1553212800,
    "game": {
      "id": 76832,
      "name": "Spiderman",
      "popularity": 41.39190295640344
    },
    "human": "2019-Mar-22",
    "m": 3,
    "platform": [
      "PC (Microsoft Windows)"
    ],
    "region": 8,
    "y": 2019
  }
]



回答2:


You could separate platform of the object and look if you have an object with the same id and add the platfor tho the array, of not create a new data set.

const
    data = [{ id: 157283, date: 1553212800, game: { id: 76882, name: "Sekiro: Shadows Die Twice", popularity: 41.39190295640344 }, human: "2019-Mar-22", m: 3, platform: { id: 48, name: "PlayStation 4" }, region: 8, y: 2019 }, { id: 12, date: 1553212800, game: { id: 76832, name: "Spiderman", popularity: 41.39190295640344 }, human: "2019-Mar-22", m: 3, platform: { id: 6, name: "PC (Microsoft Windows)" }, region: 8, y: 2019 }, { id: 157283, date: 1553212800, game: { id: 76882, name: "Sekiro: Shadows Die Twice", popularity: 41.39190295640344 }, human: "2019-Mar-22", m: 3, platform: { id: 48, name: "Xbox" }, region: 8, y: 2019 }],
    result = data.reduce((r, { platform, ...o }) => {
        var temp = r.find(({ id }) => id === o.id);
        if (!temp) r.push(temp = { ...o, platforms: [] });
        temp.platforms.push(platform);
        return r;
    }, []);

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



回答3:


Please take a look:

const data = [    {        "id": 157283,
        "date": 1553212800,
        "game": {
            "id": 76882,
            "name": "Sekiro: Shadows Die Twice",
            "popularity": 41.39190295640344
        },
        "human": "2019-Mar-22",
        "m": 3,
        "platform": {
            "id": 48,
            "name": "PlayStation 4"
        },
        "region": 8,
        "y": 2019
    },
    {
        "id": 12,
        "date": 1553212800,
        "game": {
            "id": 76832,
            "name": "Spiderman",
            "popularity": 41.39190295640344
        },
        "human": "2019-Mar-22",
        "m": 3,
        "platform": {
            "id": 6,
            "name": "PC (Microsoft Windows)"
        },
        "region": 8,
        "y": 2019
    },{        "id": 157283,
    "date": 1553212800,
    "game": {
        "id": 76882,
        "name": "Sekiro: Shadows Die Twice",
        "popularity": 41.39190295640344
    },
    "human": "2019-Mar-22",
    "m": 3,
    "platform": {
        "id": 48,
        "name": "Xbox"
    },
    "region": 8,
    "y": 2019
},
]

const filteredArr = data.reduce((acc, current) => {
  const x = acc.find(item => item.game.id === current.game.id);
    if (!x) {
      current.platform = [current.platform.name]
      return acc.concat([current]);
    } else {
      x.platform.push(current.platform.name);
      return acc;
    }
  }, []);
console.log(filteredArr);



回答4:


Here is another solution, using forEach instead of reduce. This makes use of a lookup hash that makes if faster for larger amounts of data then using find.

const data = [{"id": 157283, "date": 1553212800, "game": {"id": 76882, "name": "Sekiro: Shadows Die Twice", "popularity": 41.39190295640344}, "human": "2019-Mar-22", "m": 3, "platform": {"id": 48, "name": "PlayStation 4"}, "region": 8, "y": 2019}, {"id": 12, "date": 1553212800, "game": {"id": 76832, "name": "Spiderman", "popularity": 41.39190295640344}, "human": "2019-Mar-22", "m": 3, "platform": {"id": 6, "name": "PC (Microsoft Windows)"}, "region": 8, "y": 2019}, {"id": 157283, "date": 1553212800, "game": {"id": 76882, "name": "Sekiro: Shadows Die Twice", "popularity": 41.39190295640344}, "human": "2019-Mar-22", "m": 3, "platform": {"id": 48, "name": "Xbox"}, "region": 8, "y": 2019}];

let result = {};

data.forEach(({platform, ...release}) => {
  release.platforms = [platform.name];

  const releaseLookup = result[release.game.id];
  if (!releaseLookup) {
    result[release.game.id] = release;
  } else {
    releaseLookup.platforms.push(...release.platforms);
  }
});

console.log(Object.values(result));


来源:https://stackoverflow.com/questions/56890433/remove-duplicate-objects-from-an-array-but-merge-nested-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!