查找时间数组中最近的空闲插槽

时间:2017-02-17 07:39:10

标签: javascript arrays

我正在为诊所的队列系统工作。前台的人有两种方法可以将病人添加到队列中。

  1. 具有固定约会的患者
  2. 步入式病人
  3. 因此,例如,队列中已有四名患者,我现有的约会数组看起来像

    existing_appointments = ["09:30", "10:00", "12:15", "13:45"];
    

    患者的平均检查时间为15分钟。

    avg_wait_per_patient = 15;
    

    患者一走进去,我就找到了最适合他的时间段。

    现在说时间是09:00

    current_time = "09:00";
    

    以下函数find_free_slot()不起作用,因为它返回09:15而不是09:00,因为此广告位上没有约会。

    我的目标是,如果current_time + avg_wait_per_patient附近没有人,则该人应该被current_time位置。如果这个插槽不可用,它应该循环通过数组,除非它找到一个免费的。如果失败,应该在last_index_of_array + avg_wait上添加该人。

    function toMinutes(t) {
        return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
    }
    function reverse_toMinutes(t) {
        return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
    }
    function find_free_slot(ct,appointments,avg_wait) {
        ct = toMinutes(ct);
        free_slot = '';
        if(appointments.length==0) {
            free_slot = ct;
        } else {
            for(i=0; i<appointments.length; i++) {
                appointment = toMinutes(appointments[i]);
                if(free_slot <= appointment - avg_wait) {
                    i == 0 ?
                        free_slot = ct + avg_wait :
                        free_slot = toMinutes(appointments[i - 1]) + avg_wait;
                    break;
                }
            }   
        }
        return reverse_toMinutes(free_slot);
    }
    

    jsfiddle

4 个答案:

答案 0 :(得分:4)

问题在于:

i == 0 ?
    free_slot = ct + avg_wait :
    free_slot = toMinutes(appointments[i - 1]) + avg_wait;

如果您正在查看第一个约会(9:30)和免费广告位<= (9:30 - 15),那么您将返回ct + avg_wait9:00 + 15

我重新修改了逻辑以使其工作:

function toMinutes(t) {
  return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
}

function reverse_toMinutes(t) {
  return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
}

function find_free_slot(ct, appointments, avg_wait) {
  ct = toMinutes(ct);
  free_slot = ct;   // The first slot you want to check is "right now"

  if (appointments.length == 0)
    return reverse_toMinutes(ct);

  for (i = 0; i < appointments.length; i++) {
    appointment = toMinutes(appointments[i]);
    if (ct <= appointment + avg_wait) {        // The appointment must be later than the current appointment's end time.
      if (free_slot <= appointment - avg_wait) // Free slot is enough time before the current appointment
        return reverse_toMinutes(free_slot);   // Return the free slot

      free_slot = toMinutes(appointments[i]) + avg_wait; // Otherwise, set the free slot to `avg` after the current appointment, to check the next iteration of the loop.
    }
  }
  return reverse_toMinutes(free_slot); // No free slot has been found, `free_slot` is `last appointment + avg`
}

var appointments = ["09:30", "10:00", "12:15", "13:45"];

console.log(" time - appointment");
console.log(" 9:00 -", find_free_slot("9:00", appointments, 15));
console.log(" 9:15 -", find_free_slot("9:15", appointments, 15));
console.log(" 9:16 -", find_free_slot("9:16", appointments, 15));
console.log(" 9:31 -", find_free_slot("9:31", appointments, 15));
console.log("10:09 -", find_free_slot("10:09", appointments, 15));
console.log("11:59 -", find_free_slot("11:59", appointments, 15));
console.log("12:00 -", find_free_slot("12:00", appointments, 15));
console.log("12:01 -", find_free_slot("12:01", appointments, 15));

答案 1 :(得分:0)

您可以检查下一个插槽加上平均时间是否小于预约时间。

如果true,请返回,否则请检查时间加上平均时间是否大于或等于下一个打开的时段,然后选择时段加上平均时间。

function getMinutes(t) {
    var p = t.split(':');
    return 60 * p[0] + +p[1];
}

function find_free_slot(current_time) {
    var next_time = getMinutes(current_time);

    existing_appointments.some(function (a) {
        var minutes = getMinutes(a);
        if (next_time + avg_wait_per_patient <= minutes) {
            return true;
        }
        next_time = minutes + avg_wait_per_patient >= next_time  ? minutes + avg_wait_per_patient : next_time;
    });
    return ('0' + Math.floor(next_time / 60)).slice(-2) + ':' + ('0' +  next_time % 60).slice(-2);
}

var existing_appointments = ["09:30", "10:00", "12:15", "13:45"],
    avg_wait_per_patient = 15;

console.log(find_free_slot('09:00')); // 09:00
console.log(find_free_slot('09:15')); // 09:15
console.log(find_free_slot('09:16')); // 09:45
console.log(find_free_slot('09:45')); // 09:45
console.log(find_free_slot('09:46')); // 10:15
console.log(find_free_slot('10:00')); // 10:15
console.log(find_free_slot('10:09')); // 10:15
console.log(find_free_slot('11:59')); // 11:59
console.log(find_free_slot('12:00')); // 12:00
console.log(find_free_slot('12:01')); // 12:30

答案 2 :(得分:-1)

我做了一些编辑,现在没关系,也许你需要一个close_time和一个start_time来检查。

function toMinutes(t) {
	return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
}
function reverse_toMinutes(t) {
	return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
}

var existing_appointments = ["09:30", "10:00", "12:55", "13:45"];
var avg_wait_per_patient = 15; // in minutes
var current_time = "10:00";

function find_free_slot(ct,appointments,avg_wait) {
	ct = toMinutes(ct);
	var free_slot = '';
   
	if(appointments.length==0) {
		free_slot = ct;
	}
  else if (appointments.length==1) {
  	free_slot = toMinutes(appointments[0])+avg_wait;
	}  
  else {
    var i=0;
  	for (i=1;i<appointments.length;i++){
    	if (toMinutes(appointments[i])-toMinutes(appointments[i-1])>=2*avg_wait){
      	free_slot=toMinutes(appointments[i-1])+avg_wait;
            break;
        }    
      }
	}
  
  if (free_slot=='') free_slot=toMinutes(appointments[appointments.length-1])+avg_wait;

	return reverse_toMinutes(free_slot);
}

document.write( find_free_slot(current_time,existing_appointments,avg_wait_per_patient) );

答案 3 :(得分:-1)

我建议您使用momentjs库进行此类计算。格式。以下是如何使用时刻获得所需内容的示例。

function find_free_slot(ct,appointments,avg_wait) {
  existing_appointments.sort((a,b) => a-b);
  let possibleSlot = ct;
  for(let i=0; i<appointments.length; i++) {
    const a = appointments[i];
    if(a >= +possibleSlot + (avg_wait * 60000)) {
      appointments.splice(i, 0, possibleSlot);
      return possibleSlot;
    }
    const endOfCurrentSlot = a.clone().add(avg_wait,'minute');
    if(endOfCurrentSlot > possibleSlot) {
      possibleSlot = endOfCurrentSlot;
    }
  }
  appointments.push(possibleSlot);
  return possibleSlot;
  
}

const existing_appointments = [
  moment('09:30','HH:mm'),
  moment('10:00','HH:mm'),
  moment('13:45','HH:mm')
];
const avg_wait_per_patient = 15; // in minutes

function getSlotStr(time) {
  var slot = find_free_slot(time, existing_appointments, avg_wait_per_patient);
  return time.format('HH:mm') + ' --> ' + slot.format('HH:mm');
}

document.write( getSlotStr(moment('09:00','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:10','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:20','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:30','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:40','HH:mm')) + '<br />');
document.write( getSlotStr(moment('10:10','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:00','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:40','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:50','HH:mm')) + '<br />');
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>