首页 > 解决方案 > 将两个数组与公共对象合并

问题描述

我正在做一个从服务器获取数据的项目,每个数据都必须是这种格式

const DATA = [
  {
    title: {title: 'Main dishes'},
    data: [
      {_id: 1, type: 'Pizza'},
      {_id: 2, type: 'Burger'},
      {_id: 3, type: 'Risotto'},
    ],
  },
  {
    title: {title: 'Sides'},
    data: [
      {_id: 4, type: 'French Fries'},
      {_id: 5, type: 'Onion Rings'},
      {_id: 6, type: 'Fried Shrimps'},
    ],
  },
];

但我的问题有时会在两次或三次提取中得到相同的标题对象,所以我需要在它们之间合并并隐藏重复的数据我正在使用这个函数


  merged = (data1, data2) => {
    let arr = data1.concat(data2);
    let titles = new Map(arr.map(({title}) => [title, new Map()]));

    arr.forEach(({title, data}) => {
      let map = titles.get(title);
      data.forEach(o => map.set(o._id, o));
    });

    return Array.from(titles.entries(), ([title, map]) => ({
      title,
      data: [...map.values()],
    }));
  };

但问题是此函数仅在对象中的标题是字符串时才有效

例子 :

const DATA = [
  {
    title: {title: 'Main dishes'},
    data: [
      {_id: 1, type: 'Pizza'},
      {_id: 2, type: 'Burger'},
      {_id: 3, type: 'Risotto'},
    ],
  },
  {
    title: {title: 'Sides'},
    data: [
      {_id: 4, type: 'French Fries'},
      {_id: 5, type: 'Onion Rings'},
      {_id: 6, type: 'Fried Shrimps'},
    ],
  },
];

const DATA2 = [
  {
    title: {title: 'Sides'},
    data: [{_id: 7, type: 'Lemon'}],
  },
  {
    title: {title: 'Drinks'},
    data: [
      {_id: 8, type: 'Water'},
      {_id: 9, type: 'Coke'},
      {_id: 10, type: 'Beer'},
    ],
  },
  {
    title: {title: 'Desserts'},
    data: [
      {_id: 11, type: 'Cheese Cake'},
      {_id: 12, type: 'Ice Cream'},
    ],
  },
];


must give me an array like this 

data = [
 {
    title: {title: 'Main dishes'},
    data: [
      {_id: 1, type: 'Pizza'},
      {_id: 2, type: 'Burger'},
      {_id: 3, type: 'Risotto'},
    ],
  },
  {
    title: {title: 'Sides'},
    data: [
      {_id: 4, type: 'French Fries'},
      {_id: 5, type: 'Onion Rings'},
      {_id: 6, type: 'Fried Shrimps'},
      {_id: 7, type: 'Lemon'},
    ],
  },
{
    title: {title: 'Drinks'},
    data: [
      {_id: 8, type: 'Water'},
      {_id: 9, type: 'Coke'},
      {_id: 10, type: 'Beer'},
    ],
  },
  {
    title: {title: 'Desserts'},
    data: [
      {_id: 11, type: 'Cheese Cake'},
      {_id: 12, type: 'Ice Cream'},
    ],
  },
]

那么任何人都可以向我提出一个如何编辑该功能的解决方案吗?谢谢你

标签: javascriptreactjsreact-native

解决方案


那是因为{title: 'foo-bar'}当你这样做时,每个对象都是通过引用titles.get(title)而不是它们的值来检查的。

要么将地图中的字符串标题保存titles为键,要么使用object-hash将对象转换为标识符之类的东西。

使用字符串键:

merged = (data1, data2) => {
  let arr = data1.concat(data2);
  let titles = new Map(arr.map(({title}) => [title.title, new Map()])); // notice the `title.title` instead of `title`

  arr.forEach(({title, data}) => {
    let map = titles.get(title.title); // `title.title` instead of `title`
    data.forEach(o => map.set(o._id, o));
  });
  return Array.from(titles.entries(), ([title, map]) => ({
    title,
    data: [...map.values()],
  }));
};

并使用object-hash

import hash from 'object-hash';

merged = (data1, data2) => {
  let arr = data1.concat(data2);
  let titles = new Map(arr.map(({title}) => [hash(title), new Map()])); 

  arr.forEach(({title, data}) => {
    let map = titles.get(hash(title));
    data.forEach(o => map.set(o._id, o));
  });
  return Array.from(titles.entries(), ([title, map]) => ({
    title,
    data: [...map.values()],
  }));
};

请注意,在这种情况下,对对象进行散列可能会过大。我认为字符串解决方案就足够了。


推荐阅读