如何基于两个属性从数组中删除重复的对象?

6

我有一个房间对象数组,目前正在根据它们的room_rate_type_id属性从数组中删除重复的对象:

const rooms = [{
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

const newRooms = rooms.filter((room, index, array) => {
  const roomRateTypeIds = rooms.map(room => room.room_rate_type_id);
  // Returns the first index found.
  return roomRateTypeIds.indexOf(room.room_rate_type_id) === index;
});

console.log(newRooms);

然而,我还需要确保仅当对象的room_rate_type_id和价格都匹配时才会删除它们。

我可以理解在我的示例中提供的过滤功能是如何工作的,但我不确定如何干净地检查价格,最好使用ES6。


我已经批准了更新的问题,感谢您的反馈。 - Stephan-v
我目前正在从数组中删除重复的对象,技术上来说,你并没有这样做,而是通过过滤创建了一个新的数组.. :) - Keith
6个回答

14

您可以做到

const rooms = [
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

let result = rooms.filter((e, i) => {
    return rooms.findIndex((x) => {
    return x.room_rate_type_id == e.room_rate_type_id && x.price == e.price;}) == i;

});

console.log(result);

这将过滤掉除任何对象的第一次出现以外的所有重复项。


那是我正在寻找的干净方法。谢谢。 - Stephan-v
干净的解决方案! - Chefk5
1
这个程序具有二次时间复杂度。使用哈希映射方法和 reducefilter 可以实现线性时间复杂度。 - Sebastian Simon

3

你可以通过使用两个属性创建一个键,并且只有当该键不存在时,将对象添加到Map中,从而将数组reduce为一个Map对象。然后将Map#values展开回数组:

const rooms = [{
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

const newRooms = [...rooms.reduce((m, r) => {
  const key = `${r.room_rate_type_id}-${r.price}`; // create the key by combining both props
  return m.has(key) ? m : m.set(key, r); // if key exists skip, if not add to map
}, new Map()).values()]; // get the map values and convert back to array

console.log(newRooms);


2
对于较小的数组,您可以通过反复查找其他匹配房间来完成:
const newRooms = rooms.filter((room, index) => {
  // Only include this room if there isn't another room earlier
  // in the array that has the same values
  return !rooms.some((r, i) =>
    i < index &&
    r.room_rate_type_id == room.room_rate_type_id &&
    r.price == room.price
  );
});

const rooms = [{
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

const newRooms = rooms.filter((room, index) => {
  // Only include this room if there isn't another room earlier
  // in the array that has the same values
  return !rooms.some((r, i) =>
    i < index &&
    r.room_rate_type_id == room.room_rate_type_id &&
    r.price == room.price
  );
});

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

如果数组非常大,那么这样做效率会很低,你最好记住之前看到的组合,而不是不断地重新搜索数组。
const seenRooms = Object.create(null);
const newRooms = rooms.filter((room, index) => {
  const key = room.room_rate_type_id + "**" + room.price;
  if (seenRooms[key]) {
    return false;
  }
  seenRooms[key] = true;
  return true;
});

const rooms = [{
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

const seenRooms = Object.create(null);
const newRooms = rooms.filter((room, index) => {
  const key = room.room_rate_type_id + "**" + room.price;
  if (seenRooms[key]) {
    return false;
  }
  seenRooms[key] = true;
  return true;
});

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

这些内容是为了更加清晰易懂而编写的;如果您愿意,您可以使它们更加简洁。


1
简单方法:使用room_rate_type_idprice键的连接作为唯一键:

const rooms = [
    {room_rate_type_id: 202,price: 200},{room_rate_type_id: 202,price: 200},{room_rate_type_id: 202,price: 189},{room_rate_type_id: 190,price: 200}
];

const roomRateKeys = [];
const newRooms = rooms.filter((r, i, a) => {
    var k = r.room_rate_type_id + "" + r.price;
    if (roomRateKeys.indexOf(k) === -1) {
        roomRateKeys.push(k);
 return r;
    }
});

console.log(newRooms);


0
这样就可以了:

const rooms = [{
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

const newRooms = rooms.reduce((rooms, room) => {
  let l = rooms.filter(r => {
    return r.room_rate_type_id === room.room_rate_type_id && r.price === room.price;
  });
  if (l.length === 0) {
    return [...rooms, room]
  }
  return rooms;
}, [rooms[0]]);

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


0

const rooms = [
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 200
  },
  {
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }
];

let newRooms = rooms.filter((x, i, arr) => arr.findIndex(y => y.room_rate_type_id === x.room_rate_type_id && y.price === x.price) === i);


console.log(newRooms);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接