6

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.

2
  • I have approved the updated question, thanks for your feedback. 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.. :) Commented Sep 25, 2017 at 10:06

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

3 Comments

That is the clean approach that I am looking for. Thanks
Clean solution!
This has quadratic time complexity. Linear time complexity using the hash map approach and reduce or filter is possible.
4

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

Comments

2

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.

Comments

1

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

Comments

0

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.