Home > Mobile >  How to filter an array inside an array of objects with another array
How to filter an array inside an array of objects with another array

Time:05-13

I'm trying to solve a scheduling problem in my API, and I'm having some doubts in the manipulation of array of objects. I created a logic that returns dates that are different from those that are busy, but I can't solve the time issue. I have this array called listDates:

listDates = 
            [
                {
                    "date": "01/05/2022",
                    "hour": [
                        "7:30:00",
                        "8:00:00",
                        "8:30:00",
                        "9:00:00",
                        "9:30:00",
                        "10:00:00",
                        "10:30:00",
                        "11:00:00",
                        "11:30:00",
                        "12:00:00",
                        "12:30:00",
                        "13:00:00",
                        "13:30:00",
                        "14:00:00",
                        "14:30:00",
                        "15:00:00",
                        "15:30:00",
                        "16:00:00",
                        "16:30:00",
                        "17:00:00"
                    ]
                },
                {
                    "date": "02/05/2022",
                    "hour": [
                        "7:30:00",
                        "8:00:00",
                        "8:30:00",
                        "9:00:00",
                        "9:30:00",
                        "10:00:00",
                        "10:30:00",
                        "11:00:00",
                        "11:30:00",
                        "12:00:00",
                        "12:30:00",
                        "13:00:00",
                        "13:30:00",
                        "14:00:00",
                        "14:30:00",
                        "15:00:00",
                        "15:30:00",
                        "16:00:00",
                        "16:30:00",
                        "17:00:00"
                    ]
                },
                ...
            ]

And I want to filter out everything that is different from this array called occupiedDateHour:

occupiedDateHour =    
        [
            {
                "date": "02/05/2022",
                "hour": [
                    "16:00:00"
                ]
            },
            {
                "date": "01/05/2022",
                "hour": [
                    "14:00:00"
                ]
            }
        ]

I need something like:

newListDates = 
            [
                {
                    "date": "01/05/2022",
                    "hour": [
                        "7:30:00",
                        "8:00:00",
                        "8:30:00",
                        "9:00:00",
                        "9:30:00",
                        "10:00:00",
                        "10:30:00",
                        "11:00:00",
                        "11:30:00",
                        "12:00:00",
                        "12:30:00",
                        "13:00:00",
                        "13:30:00",
                        "14:30:00",
                        "15:00:00",
                        "15:30:00",
                        "16:00:00",
                        "16:30:00",
                        "17:00:00"
                    ]
                },
                {
                    "date": "02/05/2022",
                    "hour": [
                        "7:30:00",
                        "8:00:00",
                        "8:30:00",
                        "9:00:00",
                        "9:30:00",
                        "10:00:00",
                        "10:30:00",
                        "11:00:00",
                        "11:30:00",
                        "12:00:00",
                        "12:30:00",
                        "13:00:00",
                        "13:30:00",
                        "14:00:00",
                        "14:30:00",
                        "15:00:00",
                        "15:30:00",
                        "16:30:00",
                        "17:00:00"
                    ]
                },
                ...
            ]

If all times for a certain date have been occupied, it will not even return that specific date. The logic to return dates I wrote:

newListDates = listDates.filter(function (arr) {
                return occupiedDateHour.some(function (f) {
                    return f.date === arr.date
                });
            });

CodePudding user response:

You can use a combination of Array#reduce, Array#map and Array#filter as in the following demo:

const listDates = [ { "date": "01/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] }, { "date": "02/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] } ],
    occupiedDateHour = [ { "date": "02/05/2022", "hour": [ "16:00:00" ] }, { "date": "01/05/2022", "hour": [ "14:00:00" ] } ],
    obj = occupiedDateHour.reduce((acc,{date,hour}) => ({...acc,[date]:hour}),{}), 
    
    output = listDates.map(
        ({ date, hour }) => 
        ({
            date,
            hour: hour.filter(h => !(obj[date] || []).includes(h))
        })
    );

console.log( output );

CodePudding user response:

You can try map and find with some logic to handle filters

const listDates=[{"date":"01/05/2022","hour":["7:30:00","8:00:00","8:30:00","9:00:00","9:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00","12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00","17:00:00"]},{"date":"02/05/2022","hour":["7:30:00","8:00:00","8:30:00","9:00:00","9:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00","12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00","17:00:00"]},]
const occupiedDateHour=[{"date":"02/05/2022","hour":["16:00:00"]},{"date":"01/05/2022","hour":["14:00:00"]}]

const newListDates = listDates.map((currentDateData) => {
  const currentOccupiedDateHour = occupiedDateHour.find(dateData => dateData.date === currentDateData.date)
  if (!currentOccupiedDateHour) {
    return currentDateData
  }

  return {
    date: currentDateData.date,
    hour: currentDateData.hour.filter(currentHour => !currentOccupiedDateHour.hour.includes(currentHour))
  }
})

console.log(newListDates)
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

I'd start by transforming occupiedDateHour into an object which is better suited for the filtering:

const occupiedDateHour = [
  { "date": "02/05/2022", "hour": ["16:00:00"] },
  { "date": "01/05/2022", "hour": ["14:00:00"] }
];

const occupiedDateHourIndex = occupiedDateHour.reduce((acc, el) => {
  acc[el.date] = el.hour;
}, {});

producing a structure like this:

{
  "02/05/2022" : ["16:00:00"], "01/05/2022": ["14:00:00"]
}

Add a filtering function:

const filterHours = (hours, excludeHours) => {
  return hours.filter(h => !excludeHours.includes(h));
};

With that, you can do an O(1) lookup of the list of hours to exclude for a given date; and filter the hours of a given date by that exclusion list.

Apply the filter and you're done:

const newListDates = listDates.map(el => {
  const date = el.date;
  const hour = filterHours(el.hour, occupiedDateHourIndex[date]);
  return { date, hour }
})

Demo...

const occupiedDateHour = [
  {
    "date": "02/05/2022",
    "hour": ["16:00:00"]
  },
  {
    "date": "01/05/2022",
    "hour": ["14:00:00"]
  }
];

const occupiedDateHourIndex = occupiedDateHour.reduce((acc, el) => {
  acc[el.date] = el.hour;
  return acc;
}, {});


const filterHours = (hours, excludeHours) => {
  return hours.filter(h => !excludeHours.includes(h));
};

const listDates = [ { "date": "01/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] }, { "date": "02/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] } ]

const newListDates = listDates.map(el => {
  const date = el.date;
  const hour = filterHours(el.hour, occupiedDateHourIndex[date]);
  return { date, hour }
})

console.log(JSON.stringify(newListDates, null, 4))

  • Related