[英]How to compare every number in an array against each other? (javascript)
[英]Compare each element in an array against every other element
我需要比较重叠的时间表,范围从2到无限多个时间表。
例如,具有3个调度的数组如下所示:
var dateRanges = [
{
DaysOfWeek: ['Sun', 'Mon'],
StartTime: "01:00",
StopTime: "17:00",
AllDay: false
},
{
DaysOfWeek: ['Tues', 'Wed'],
StartTime: "12:00",
StopTime: "21:59",
AllDay: true
},
{
DaysOfWeek: ['Thur', 'Sun'],
StartTime: "12:00",
StopTime: "21:59",
AllDay: true
}
]
我正在努力弄清楚如何将所有数组相互比较。 到目前为止,我有这个
checkScheduleForOverlap: function (dateRanges) {
var result = dateRanges.reduce((result, current, i, arr) => {
// console.log(previous, current);
// get the previous range
if (i === 0) { return result; }
var previous = arr[i - 1];
// Schedule1
var startTime1 = new Date('1970-01-01T' + previous.StartTime + 'Z');
var stopTime1 = new Date('1970-01-01T' + previous.StopTime + 'Z');
// Schedule2
var startTime2 = new Date('1970-01-01T' + current.StartTime + 'Z');
var stopTime2 = new Date('1970-01-01T' + current.StopTime + 'Z');
previous.DaysOfWeek.forEach(function (prevDay) {
console.log(prevDay);
current.DaysOfWeek.forEach(function (currDay) {
console.log(currDay);
if (prevDay === currDay) {
var overlap = (startTime1 <= stopTime2) && (stopTime1 >= startTime2);
// store the result
if (overlap) {
// yes, there is overlap
result.overlap = true;
// store the specific ranges that overlap
result.days.push(currDay);
}
}
});
});
return result;
// seed the reduce
}, { overlap: false, days: [] });
// return the final results
console.log(result);
return result;
}
但是,它仅将第二个数组与第一个数组进行比较,第三个数组与第二个数组进行比较。 它还需要将第三个与第一个进行比较。 (如果有4个时间表,则每个时间表都需要与其他时间表进行比较。)
我是否处在正确的轨道上,如何做才能使每个DaysOfWeek时间表将StartTime和StopTime与另一个时间表中的值进行比较?
我使用静态日期创建了一个伪造的日期对象,而我只是比较时间值。
如果这不是一种有效的方法,我愿意采取完全不同的方法。
让我们集中讨论问题的一部分,即比较多个数组之间的项目。 目前,比较的实际逻辑并不重要。
这一切都始于嵌套的for循环:
var arr1 = [ "A", "B", "C" ]; var arr2 = [ "1", "2", "3" ]; // Runs arr1.length * arr2.length = 9 times for (let i = 0; i < arr1.length; i += 1) { for (let j = 0; j < arr2.length; j += 1) { console.log( "run", i * arr2.length + j, "result", arr1[i], arr2[j] ); } }
一旦有了一个遍历两个数组的所有对的函数,剩下要做的就是从单个数组列表中查找所有可能的对:
const arrays = [ [ "A" ], [ "B" ], [ "C" ] ]; for (let i = 0; i < arrays.length - 1; i += 1) { // ^^^ for (let j = i + 1; j < arrays.length; j += 1) { // ^^^^^ console.log( JSON.stringify(arrays[i]), JSON.stringify(arrays[j]) ); } }
现在我们已经涵盖了基础知识,我们可以将它们链接在一起并进行重构。 我不得不承认,重构有点个人喜好,将for
循环包装在函数中而无需其他更改是完全可以的。
我已经命名了第一个原理combinations
,并使用了reduce
和map
而不是for
循环。 第二个for
循环现在包含在allPairs
。
// Utilities: const combinations = ([xs, ys]) => xs.reduce( (cs, x) => cs.concat(ys.map(y => [x, y])), [] ); const allPairs = (xs) => xs.reduce( (ps, x, i) => ps.concat(xs.slice(i + 1).map(y => [x, y])), [] ); const flatten = xxs => xxs.reduce((xs, ys) => xs.concat(ys)) const findMatches = (matchFn, arrays) => flatten( allPairs(arrays).map(combinations)).filter(matchFn); // App: // Let's just stick to an easy example const overlap = ([x, y]) => x === y; console.log( findMatches( overlap, [ [ 1, 2 ], [ 1, 3 ], [ 1, 2, 3], [ 4, 5 ], [ 1 ] ] ) );
这种方法返回一对重叠的元素。 您必须包括自己的overlaps
功能。 通过使用find
而不是filter
,它可以返回第一对重叠对,从而可以提高效率。 如果您真的想尽早返回,甚至在构造所有配对组合之前,就必须多移动一些东西(但是我无法想象性能会成为问题)。
我可以使用以下代码来使其工作。 可以提高效率,但对于较小的列表,效果很好。
/**
* Compares to comparable objects to find out whether they overlap.
* It is assumed that the interval is in the format [from,to) (read: from is inclusive, to is exclusive).
* A null value is interpreted as infinity
*/
checkScheduleForOverlap: function (dateRanges) {
function dateRangeOverlaps (a_start, a_end, b_start, b_end) {
if (a_start <= b_start && b_start <= a_end) return true; // b starts in a
if (a_start <= b_end && b_end <= a_end) return true; // b ends in a
if (b_start < a_start && a_end < b_end) return true; // a in b
return false;
}
function multipleDateRangeOverlaps () {
var i, j;
if (arguments.length % 2 !== 0)
throw new TypeError('Arguments length must be a multiple of 2');
for (i = 0; i < arguments.length - 2; i += 2) {
for (j = i + 2; j < arguments.length; j += 2) {
if (
dateRangeOverlaps(
arguments[i], arguments[i + 1],
arguments[j], arguments[j + 1]
)
) return true;
}
}
return false;
}
var result = {
overlappingDays: [],
overlap: false
};
// for every Schedule
for (let i = 0; i < dateRanges.length; i++) {
var current = dateRanges[i];
// current Schedule
var startTime1 = current.StartTime;
var stopTime1 = current.StopTime;
current.DaysOfWeek.forEach(function (currDay) {
// console.log('currentScheduleDay', currDay);
// for every OTHER schedule
for (let j = 0; j < dateRanges.length; j++) {
var nextSchedule = dateRanges[j];
if (j === i) {
continue;
}
nextSchedule.DaysOfWeek.forEach(function (nextDay) {
// console.log('nextScheduleDay', nextDay);
if (nextDay === currDay) {
// next Schedule
var startTime2 = nextSchedule.StartTime;
var stopTime2 = nextSchedule.StopTime;
// var overlap = (startTime1 <= stopTime2) && (stopTime1 >= startTime2);
var overlap = multipleDateRangeOverlaps(startTime1, stopTime1, startTime2, stopTime2);
// store the result
if (overlap) {
// yes, there is overlap
result.overlap = true;
// store the specific ranges that overlap
result.overlappingDays.push(currDay);
}
}
});
}
});
}
// remove duplicates in result
var obj = {};
for (var i = 0, len = result.overlappingDays.length; i < len; i++) {
obj[result.overlappingDays[i]] = result.overlappingDays[i];
}
result.overlappingDays = new Array();
for (var key in obj) {
result.overlappingDays.push(obj[key]);
}
if (result.overlappingDays) {
this.scheduleDaysOverlap = result.overlappingDays;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.