Reputation: 453
I'm trying to delete duplicate elements from a dictionary when the key values "hour_from" and "hour_to" are the same. I'm using a double for (I don't remember other less cost algorithms to do it) but I'm having problems with index values.
var hours_array = [
{day: "Mon", hour_from: "00:00", hour_to: "00:00"},
{day: "Mon", hour_from: "00:00", hour_to: "00:16"},
{day: "Mon", hour_from: "00:00", hour_to: "00:16"},
{day: "Thu", hour_from: "00:00", hour_to: "00:25"},
{day: "Mon", hour_from: "00:00", hour_to: "00:33"},
{day: "Fri", hour_from: "00:00", hour_to: "00:83"},
{day: "Sat", hour_from: "02:00", hour_to: "05:33"},
{day: "Thu", hour_from: "02:00", hour_to: "05:33"},
{day: "Wed", hour_from: "12:00", hour_to: "14:00"},
{day: "Sun", hour_from: "22:25", hour_to: "13:45"}]
for (let i=0; i< hours_array.length; i++){
for (let j=0; j<=hours_array.length; j++){
if ((hours_array[i]['hour_from'] == hours_array[j]['hour_from']) && (hours_array[i]['hour_to'] == hours_array[j]['hour_to'])){
delete hours_array[j];
}
}
}
I thought it is an error with index values:
Edit: Needed result:
var hours_array = [
{day: "Mon", hour_from: "00:00", hour_to: "00:00"},
{day: "Mon", hour_from: "00:00", hour_to: "00:16"},
{day: "Thu", hour_from: "00:00", hour_to: "00:25"},
{day: "Mon", hour_from: "00:00", hour_to: "00:33"},
{day: "Fri", hour_from: "00:00", hour_to: "00:83"},
{day: "Sat", hour_from: "02:00", hour_to: "05:33"},
{day: "Wed", hour_from: "12:00", hour_to: "14:00"},
{day: "Sun", hour_from: "22:25", hour_to: "13:45"}]
Any suggestion? Any some more efficient algorithm? Thanks for reading!
Upvotes: 0
Views: 74
Reputation: 15530
You may go lazy way with Array.prototype.reduce()
along with Array.prototype.find()
.
const src = [{day:"Mon",hour_from:"00:00",hour_to:"00:00"},{day:"Mon",hour_from:"00:00",hour_to:"00:16"},{day:"Mon",hour_from:"00:00",hour_to:"00:16"},{day:"Thu",hour_from:"00:00",hour_to:"00:25"},{day:"Mon",hour_from:"00:00",hour_to:"00:33"},{day:"Fri",hour_from:"00:00",hour_to:"00:83"},{day:"Sat",hour_from:"02:00",hour_to:"05:33"},{day:"Thu",hour_from:"02:00",hour_to:"05:33"},{day:"Wed",hour_from:"12:00",hour_to:"14:00"},{day:"Sun",hour_from:"22:25",hour_to:"13:45"}],
dedupe = src.reduce((res, item) =>
(
!res.find(({hour_from, hour_to}) =>
hour_from == item.hour_from && hour_to == item.hour_to) ?
res.push(item) :
true, res
), [])
console.log(dedupe)
Upvotes: 1
Reputation: 11001
Use reduce
method with combining Object.values
.
var hours_array = [
{ day: "Mon", hour_from: "00:00", hour_to: "00:00" },
{ day: "Mon", hour_from: "00:00", hour_to: "00:16" },
{ day: "Mon", hour_from: "00:00", hour_to: "00:16" },
{ day: "Thu", hour_from: "00:00", hour_to: "00:25" },
{ day: "Mon", hour_from: "00:00", hour_to: "00:33" },
{ day: "Fri", hour_from: "00:00", hour_to: "00:83" },
{ day: "Sat", hour_from: "02:00", hour_to: "05:33" },
{ day: "Thu", hour_from: "02:00", hour_to: "05:33" },
{ day: "Wed", hour_from: "12:00", hour_to: "14:00" },
{ day: "Sun", hour_from: "22:25", hour_to: "13:45" }
];
const updated = Object.values(
hours_array.reduce(
(acc, curr) => ({
...acc,
[`${curr.hour_from}-${curr.hour_to}`]: { ...curr }
}),
{}
)
);
console.log(updated);
Upvotes: 0
Reputation: 386654
You could filter the array with the help of a Set
.
If a hash value (build from hour_from
and hour_to
) is in the set, the item is filtered out. If not, then the hash is taken to the set and the item is used.
var getKey = ({ hour_from, hour_to }) => [hour_from, hour_to].join('|'),
hours_array = [{ day: "Mon", hour_from: "00:00", hour_to: "00:00" }, { day: "Mon", hour_from: "00:00", hour_to: "00:16" }, { day: "Mon", hour_from: "00:00", hour_to: "00:16" }, { day: "Thu", hour_from: "00:00", hour_to: "00:25" }, { day: "Mon", hour_from: "00:00", hour_to: "00:33" }, { day: "Fri", hour_from: "00:00", hour_to: "00:83" }, { day: "Sat", hour_from: "02:00", hour_to: "05:33" }, { day: "Thu", hour_from: "02:00", hour_to: "05:33" }, { day: "Wed", hour_from: "12:00", hour_to: "14:00" }, { day: "Sun", hour_from: "22:25", hour_to: "13:45" }],
unique = hours_array.filter((s => o => !s.has(getKey(o)) && s.add(getKey(o)))(new Set));
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 1150
In this line for (let j=0; j<=hours_array.length; j++){
you can run out of the array's boundries. In your situation the array.length is 10, however when you try to access the element with index 10 you get undefined, because your last index is 9. You either have to change <=
to <
or reduce the length by 1. See solution below:
for (let i=0; i< hours_array.length; i++){
for (let j=0; j<hours_array.length; j++){
if ((hours_array[i]['hour_from'] == hours_array[j]['hour_from']) && (hours_array[i]
['hour_to'] == hours_array[j]['hour_to'])){
delete hours_array[j];
}
}
}
Edit: Ok you understand this issue, the next problem is that you delete an element if the array while you are still looping. There are many ways to fix this, but the easiest one is to create a new array and push the unique elements to that new array. Let me know if you need help with that.
Upvotes: 0