Javascript-从对象数组中删除重复的ID

时间:2019-10-08 13:02:02

标签: javascript arrays duplicates

采用以下两个数组:

const array1 = [
  {
    props: {
      type : 'text',
      id : 'item1',
      name : 'item1',
      value : '@item1@',
    },
  },
  {
    props: {
      type: 'hidden',
      id: 'item2',
      name: 'item2',
      value: '@item2@',
    },
  }
];

const array2 = [
  {
    props: {
      type: 'hidden',
      id: 'item1',
      name: 'item1',
      value: '@item1@',
    },
  }
];

我要执行的操作是将它们连接到单个数组中,并删除基于id属性的所有重复项。但是,这里需要说明的是,typehidden的对象必须存在。

因此,基本上我应该留给array1的内容,因为来自array2的重复项的type值为hidden,就像这样:

// Result
[
  {
    props: {
      type : 'text', // Note the type here is "text"
      id : 'item1',
      name : 'item1',
      value : '@item1@',
    },
  },
  {
    props: {
      type: 'hidden',
      id: 'item2',
      name: 'item2',
      value: '@item2@',
    },
  }
];

我可以使用以下命令轻松地将它们连接起来:

const array = array1.concat(array2);

我的想法是然后使用Filter,但我有点脑筋急转弯。到目前为止,这是我想出的:

const concat = (array1, array2) => {
  const array = array1.concat(array2);
  const ids = [];

  // Create array of ID's
  for (const i in array1) {
    ids.push(array1[i].props.id);
  }

  return array.filter((obj) => {
    if (obj.props.type !== 'hidden' && ids.includes(obj.props.id)) {
      return true;
    }

    return false;
  });
};

在这里使用Reduce会更好吗?

这是我到目前为止所掌握的JSFiddle:https://jsfiddle.net/64uprbhn/

2 个答案:

答案 0 :(得分:5)

您可以

  1. 从第一个数组创建id => object的地图
  2. 遍历第二个数组,或者
    • 添加地图中尚未添加的项目
    • 检查当前项是否不是type: "hidden"并覆盖其他项
    • 否则丢弃该物品
  3. 从地图创建新数组

const array1 = [
  {
    props: {
      type : 'text',
      id : 'item1',
      name : 'item1',
      value : '@item1@',
    },
  },
  {
    props: {
      type: 'hidden',
      id: 'item2',
      name: 'item2',
      value: '@item2@',
    },
  },
  {
    props: {
      type: 'hidden',
      id: 'item3',
      name: 'item3',
      value: '@item3@',
    },
  }
];

const array2 = [
  {
    props: {
      type: 'hidden',
      id: 'item1',
      name: 'item1',
      value: '@item1@',
    },
  },
  {
    props: {
      type: 'text',
      id: 'item3',
      name: 'item3',
      value: '@item3@',
    },
  }
];

//1. create a map from id => object pairs
const map = new Map(array1.map(obj => [obj.props.id, obj]));

//2. go over the second array
array2.forEach(obj => {
  if (!map.has(obj.props.id) //not a duplicate
    || obj.props.type !== "hidden") { //is not hidden
    //insert
    map.set(obj.props.id, obj);
  }
});

//3. convert back into array
const merged = [...map.values()];

console.log(merged);

为了记录,您基本上可以使用.filter做相同(或非常相似)的事情,但是您必须对每个项目进行O(n)查找。地图可确保更快的查找。

答案 1 :(得分:0)

const array1 = [
  {
    props: {
      type : 'text',
      id : 'item1',
      name : 'item1',
      value : '@item1@',
    },
  },
  {
    props: {
      type: 'hidden',
      id: 'item2',
      name: 'item2',
      value: '@item2@',
    },
  }
];

const array2 = [
  {
    props: {
      type: 'hidden',
      id: 'item1',
      name: 'item1',
      value: '@item1@',
    },
  }
];

function getUnique(arr, comp) {

  const unique = arr
    .map(e => e[comp])

    // store the keys of the unique objects
    .map((e, i, final) => final.indexOf(e) === i && i)

    // eliminate the dead keys & store unique objects
    .filter(e => arr[e]).map(e => arr[e]);

  return unique;
}

const arr = array1.concat(array2);

console.log(getUnique(arr, 'id'));