0

How to remove duplicates objects in array and the original value based on 2 properties

This what i do but this return the original

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

i want the result to be only

{
    room_rate_type_id: 202,
    price: 189
  },
  {
    room_rate_type_id: 190,
    price: 200
  }

MOz
  • 39
  • 6
  • why price 189 for 202? – Nina Scholz Nov 18 '21 at 15:49
  • i want to filter based on this two property room_rate_type_id , price not only room_rate_type_id – MOz Nov 18 '21 at 15:50
  • Does this answer your question? [How to remove all duplicates from an array of objects?](https://stackoverflow.com/questions/2218999/how-to-remove-all-duplicates-from-an-array-of-objects) – jabaa Nov 18 '21 at 15:56
  • What you need is to transform this list to a hash where keys are rate types and values are lists of distinct prices. – Sinan Ünür Nov 18 '21 at 16:00

5 Answers5

1

I presume you wish to find the cheapest price for each room_rate_type_id, we can do this using Array.reduce().

We get the cheapest price for each rate type id by looping over each entry and replacing the value for each rate id if the entry price is lower than the current lowest value:

    
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 result = Object.values(rooms.reduce((acc, cur) => { 
    if (!acc[cur.room_rate_type_id] || acc[cur.room_rate_type_id].price > cur.price) acc[cur.room_rate_type_id] = cur;
    return acc;
}, {}));

console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
0

I'd like to create result array and use rooms.forEach(...) instead of rooms.filter(...) to iterate through the items in rooms and on the every iteration we can check if there's an object with the same room_rate_type_id and price property values. To check the object existence in the result array I'm using result.findIndex(...). If this method returns a value 0 or greater than 0, that means we already have item with these values and no need to add it to the result array, otherwise result doesn't contain similar object and we need to add. Here's the example how I 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 result = [];
rooms.forEach(item => {
    if (result.findIndex(x => x.room_rate_id === item.room_rate_id && x.price === item.price) < 0) {
        result.push(item);
    }
});
console.log(result)
Igor Belykh
  • 101
  • 5
  • 13
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 18 '21 at 17:08
0

You could take a Map and filter the values.

const
    getKey = o => ['room_rate_type_id', 'price'].map(k => o[k]).join('|'),
    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 }],
    result = [
        ...rooms
            .reduce(
                (m, o) => (k => m.set(k, !m.has(k) && o))(getKey(o)),
                new Map
            )
            .values()
        ]
        .filter(Boolean);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

If your are searching for duplicates object in your array (meaning same price and same room_rate_type_id) I would recomment to use JSON.stringify() and JSON.parse() as follow:

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 result = rooms.map(room => JSON.stringify(room)).filter((room, index, arr) => arr.indexOf(room) === index).map(room => JSON.parse(room))

console.log(result)
0

This is the long form of another answer. First, map the list to rate types and available prices for those rates. Then, associate each rate type with the lowest available 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
  }
];

let options = {};

for (const entry of rooms) {
    options[entry.room_rate_type_id] ||= [];
    options[entry.room_rate_type_id].push(entry.price);
}

console.log(options);

for (const rate_type in options) {
    const price = Math.min(...options[rate_type]);
    options[rate_type] = price;
}

console.log(options);
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339