根据预订的时段将可用的时隙数组分为多个块

时间:2019-06-05 14:52:10

标签: javascript arrays lodash chunks

我有2个数组:

  1. 生成了一天中从特定开始时间到结束时间的时间戳记(每个(1800 difference in each timestamp) 30分钟)。
  2. 我从API响应中获得了预订的广告位响应。

我需要合并两个数组以形成代表可用插槽和预订插槽的对象数组:

let availableTimeslots = [
  1559709000,
  1559710800,
  1559712600,
  1559714400,
  1559716200,
  1559718000,
  1559719800,
  1559721600,
  1559723400,
  1559725200,
  1559727000,
  1559728800,
  1559730600,
  1559732400,
  1559734200,
  1559736000,
  1559737800,
  1559739600
];

let bookedTimeSlots = {
  bookings: [
    {
      timestamp: {
        from: 1559719800,
        to: 1559723400
      }
    },
    {
      timestamp: {
        from: 1559730600,
        to: 1559732400
      }
    }
  ]
};

我需要创建对象数组,例如:

[
  {
    available: true,
    timeslots: [1559709000, 1559710800, 1559712600, 1559714400, 1559716200, 1559718000]
  },
  {
    available: false,
    timeslots: [1559719800, 1559721600, 1559723400]
  },
  {
    available: true,
    timeslots: [1559725200, 1559727000, 1559728800]
  },
  {
    available: false,
    timeslots: [1559730600, 1559732400]
  },
  {
    available: true,
    timeslots: [1559732400, 1559734200, 1559736000, 1559737800, 1559739600]
  }
];

我对如何进行此操作感到非常困惑 我正在考虑将availableTimeslots中的值替换为所需的预订空位对象,然后将所有非对象值替换为{available: true, timeslots: [...]}

bookedTimeSlots.bookings.map((bs, i)=> {
            let ai = availableTimeslots.findIndex(bs.timestamp.from);
            ai > -1 && (availableTimeslots[ai]={available: false, x  : [..._.range(bs.timestamp.from, bs.timestamp.to, 1800)]});
        })

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

有很多方法可以解决此问题。一种简化的方法是利用以下事实:时隙之间存在已知的增量(1,800),因此您可以尝试为每个“大块”生成一个新的时隙数组,而不是尝试分割时隙数组和结束时隙。在下面的代码段中,您可以看到采用此方法的基本递归解决方案:

const INCREMENT = 1800;

// Utility function to generate an inclusive range
function rangeIncl(start, end, incr = INCREMENT) {
  return start < end ? [start, ...rangeIncl(start + incr, end)] : [end];
}

function timeslotGroups(startTimeslot, endTimeslot, bookings) {
  const [booking, ...restBookings] = bookings;

  if (booking) {
    if (startTimeslot < booking.from) {
      // startTimeslot is before next booking.from; add available group
      return [
        {
          available: true,
          timeslots: rangeIncl(startTimeslot, booking.from - INCREMENT),
        },
        ...timeslotGroups(booking.from, endTimeslot, bookings),
      ];
    }

    if (startTimeslot <= booking.to) {
      // startTimeslot is between booking.from and .to; add not-available group
      return [
        {
          available: false,
          timeslots: rangeIncl(booking.from, booking.to),
        },
        ...timeslotGroups(booking.to + INCREMENT, endTimeslot, restBookings),
      ];
    }

    // startTimeslot is after booking.to; try again with next booking
    return timeslotGroups(startTimeslot, endTimeslot, restBookings);
  }
  
  // No more bookings; add final available group if there are any
  // timeslots left
  return startTimeslot < endTimeslot ? [
    {
      available: true,
      timeslots: rangeIncl(startTimeslot, endTimeslot),
    },
  ] : [];
}

const availableTimeslots = [
  1559709000, 1559710800, 1559712600, 1559714400, 1559716200, 1559718000,
  1559719800, 1559721600, 1559723400, 1559725200, 1559727000, 1559728800,
  1559730600, 1559732400, 1559734200, 1559736000, 1559737800, 1559739600,
];

const bookedTimeslots = {
  bookings: [
    { timestamp: { from: 1559719800, to: 1559723400 }},
    { timestamp: { from: 1559730600, to: 1559732400 }},
  ],
};

const firstTimeslot = availableTimeslots[0];
const lastTimeslot = availableTimeslots[availableTimeslots.length - 1];
// Bookings will be easier to work with as an array of { from, to } objects
const bookings = bookedTimeslots.bookings.map(booking => booking.
timestamp);

const groups = timeslotGroups(firstTimeslot, lastTimeslot, bookings);
console.log(groups);

请注意,此代码假定bookings将按时间顺序排列。

答案 1 :(得分:0)

我这样做是这样的:https://jsfiddle.net/saurabhsharma/a6qoyfhd/

let availableTimeslots = [
    1559709000,
    1559710800,
    1559712600,
    1559714400,
    1559716200,
    1559718000,
    1559719800,
    1559721600,
    1559723400,
    1559725200,
    1559727000,
    1559728800,
    1559730600,
    1559732400,
    1559734200,
    1559736000,
    1559737800,
    1559739600
];

let parsedArr = [];

let bookedTimeSlots = {
    bookings: [{
            timestamp: {
                from: 1559719800,
                to: 1559723400
            }
        },
        {
            timestamp: {
                from: 1559730600,
                to: 1559732400
            }
        }
    ]
};


/* parsedArr = availableTimeslots.map((ts, i) => {
    return bookedTimeSlots.bookings.map((bs, n)=> {
        let x = [];
        if(ts<bs.timestamp.from) {
            x.push(ts);
        } else { return {available: true, timeslots: [...x]}}
    })
}) */


bookedTimeSlots.bookings.map((bs, i) => {
    let ai = availableTimeslots.indexOf(bs.timestamp.from);
    if (ai > -1) {
        let range = [..._.range(bs.timestamp.from, bs.timestamp.to, 1800)]
        availableTimeslots[ai] = {
            available: false,
            timestamp: [...range]
        };
        availableTimeslots.splice(ai + 1, range.length - 1);
    }
})

console.log("availableTimeSlot", availableTimeslots);

let tempArr = [];
let startIndex = '';
let timeStampParsed = [...availableTimeslots];

while(!timeStampParsed.every((ts)=>typeof ts == 'object')) {
	timeStampParsed.map((ts, i) => {
        if (typeof ts != "object") {
            tempArr.push(ts);
            startIndex === '' && (startIndex = i);
            //Case i reached the last index
            if (i == timeStampParsed.length - 1) {
                let range = [..._.range(timeStampParsed[startIndex], timeStampParsed[i]+1800, 1800)];
                console.log(range);
                timeStampParsed[startIndex] = {
                    available: true,
                    timestamp: [...range]
                };
                timeStampParsed.splice(startIndex + 1, range.length);
                tempArr = [];
                startIndex = '';
            }
        } else {
            if (tempArr.length > 0 && startIndex !== '') {
                let range = [..._.range(timeStampParsed[startIndex], timeStampParsed[i-1], 1800)];
                timeStampParsed[startIndex] = {
                    available: true,
                    timestamp: [...range]
                };
                timeStampParsed.splice(startIndex+1, range.length);
                tempArr = [];
                startIndex = '';
            }
        }
    })
}

console.log("TIMESTAMP PARSED =>", timeStampParsed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

请提出一种更好的方法。