1

I have two arrays of objects:

\\offers
[
{DeskUID: "B11A13", Day: 06 Jun 2020}
{DeskUID: "B11A13", Day: 07 Jun 2020}
{DeskUID: "B12B34", Day: 23 Jun 2020}
]

\\reservations
[
{DeskUID: "B11A13", Day: 06 Jun 2020, Name: "Mike"}
{DeskUID: "B12B34", Day: 23 Jun 2020, Name: "Ali"}
]

I would like to have a result where are available offers, that means only the offers without already reserved desks.

\\result
[
{DeskUID: "B11A13", Day: 07 Jun 2020}
]

How to get the difference between two arrays of objects in JavaScript

I already tried solutions on the link above but without success, I just got a result array as sum of all objects from the two arrays.

            function comparer(otherArray){
                return function(current){
                var reserveDay = new Date (current.Day)
                    return otherArray.filter(function(other){
                        var offerDay = new Date (other.Day)
                        return other.DeskUID == current.DeskUID && offerDay == reserveDay
                    }).length == 0;
                }
            }

            var onlyInA = offers.filter(comparer(reservations));
            var onlyInB = reservations.filter(comparer(offers));

            result = onlyInA.concat(onlyInB);
Milan
  • 25
  • 6

3 Answers3

1

You could take a Set and filter the reservations.

var getKey = ({ DeskUID, Day }) => [DeskUID, Day].join('|'),
    offers = [{ DeskUID: "B11A13", Day: "2020-06-06" }, { DeskUID: "B11A13", Day: "2020-06-07" }, { DeskUID: "B12B34", Day: "2020-06-23" }],
    reservations = [{ DeskUID: "B11A13", Day: "2020-06-06", Name: "Mike" }, { DeskUID: "B12B34", Day: "2020-06-23", Name: "Ali" }],
    reservationsSet = new Set(reservations.map(getKey)),
    open = offers.filter(o => !reservationsSet.has(getKey(o)));

console.log(open);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You can do in a single function, like:

const available = offers.filter(offer => { 
  return reservations.findIndex(reservation => reservation.DeskUID === offer.DeskUID && sameDay(new Date(reservation.Day), new Date(offer.Day))) === -1;
});

function sameDay(d1, d2) {
  return (
    d1.getFullYear() === d2.getFullYear() &&
    d1.getMonth() === d2.getMonth() &&
    d1.getDate() === d2.getDate()
  );
}

console.log(available);

So, what is exactly happening...

  • offers.filter runs a check for each element in the offers array.
  • reservations.findIndex will try to find if there is already a reservation for that offer. It does by going into the reservations array and checking if there is the same unique ID and same date for the offer that is currently filtering.
  • If the result is equal to -1 it means that there is no reservation for that offer. Therefore it is available.

I've used the dates as string for the sake of simplicity, you can just alter to Date object. Hope it helps!

EDIT

I've added a small helper function for you to compare if the dates are from the same day. You can check this answer for a more detailed explanation: how to tell if two dates are in the same day?

perellorodrigo
  • 536
  • 5
  • 11
  • 1
    Thank you, for your feedback. Days in my arrays are "Date" data type. How can I adjust your solution? ``` const available = convenientOffers.filter(offer => { return reservedDesks.findIndex(reservation => reservation.DeskUID === offer.DeskUID && (new Date (reservation.Day)) !== (new Date (offer.Day))) !== -1; }); console.log(available); ``` – Milan May 31 '20 at 13:49
  • I've edited the answer to show how can you compare the dates. You can do `(new Date (reservation.Day)) !== (new Date (offer.Day))` because each date is a different instance of the Date object. Therefore they will never be the same (even if the dates are the same). I've also fixed a little logic error in the code – perellorodrigo May 31 '20 at 23:56
  • I found out that this solution is not working in IE11. Is it possible to use some other method which is suitable for IE11? – Milan Jun 01 '20 at 09:32
  • IE console says "Syntax Error". I assume it is due to the arrow functions. – Milan Jun 01 '20 at 10:17
  • It is likely. You can just replace to the usual functions, it will work the same way – perellorodrigo Jun 01 '20 at 10:45
1

You can simply filter it with some inside it.

var offers = [{ DeskUID: "B11A13", Day: "2020-06-06" }, { DeskUID: "B11A13", Day: "2020-06-07" }, { DeskUID: "B12B34", Day: "2020-06-23" }];
var reservations = [{ DeskUID: "B11A13", Day: "2020-06-06", Name: "Mike" }, { DeskUID: "B12B34", Day: "2020-06-23", Name: "Ali" }];

var result = offers.filter(k=>!reservations.some(d=>d.DeskUID == k.DeskUID && d.Day==k.Day));

console.log(result);
gorak
  • 5,233
  • 1
  • 7
  • 19