最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to remove duplicates objects in array based on 2 properties? - Stack Overflow

programmeradmin3浏览0评论

I have an array of room objects and I am currently removing duplicates objects from the array based on their room_rate_type_id property:

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);

I have an array of room objects and I am currently removing duplicates objects from the array based on their room_rate_type_id property:

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);

However I also need to make sure that objects only get removed if not only their room_rate_type_id matches but also their price.

I can understand how the filter functionality works in my given example but I am unsure how to cleanly do a check for the price as well, preferably in ES6.

Share Improve this question edited Sep 25, 2017 at 9:59 Milan Chheda 8,2493 gold badges22 silver badges35 bronze badges asked Sep 25, 2017 at 9:53 Stephan-vStephan-v 20.3k32 gold badges121 silver badges210 bronze badges 2
  • I have approved the updated question, thanks for your feedback. – Stephan-v Commented Sep 25, 2017 at 9:59
  • I am currently removing duplicates objects from the array, well technically your not, your creating a new array from a filter.. :) – Keith Commented Sep 25, 2017 at 10:06
Add a comment  | 

6 Answers 6

Reset to default 14

You can do

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);

This would filter all duplicates except the first occurrence of any object

You can reduce the array to a Map object by creating a key from both properties, and adding the object to the Map only if the key doesn't already exist. Then spread the Map#values back to an array:

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);

For a smallish array, you can do it by repeating looking for other matching rooms:

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;
}

If the array is really large, that gets inefficient and you may be better off remembering combinations you've seen before rather than constantly re-searching the array:

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;
}

Those are written for clarity; you can make them more concise if you like.

Simple approach: using concatenation of room_rate_type_id and price keys as unique key:

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);

This would do it:

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; }

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);

发布评论

评论列表(0)

  1. 暂无评论