从给定范围中排除多个范围

时间:2016-12-31 13:25:18

标签: javascript

我有一个范围值为library(data.table) library(lubridate) dcast(setDT(df1)[order(dmy(Invoice.Date))] , Model + Components ~ paste0("Garage", Garage), value.var = "Unit.Price", function(x) x[1]) # Model Components GarageA GarageB #1: BMW HL 700 800 #2: Honda HL 300 600 #3: Honda TL 200 700 #4: Hyundai HL 500 NA #5: Porsche TL 800 800 的数组。然后在第二个数组中我有其他范围,如[1,35]等。

现在我需要从第一个中减去这些范围,并得到像这样的值 [2,5], [8,9](取出[1-1]),然后是2-5,然后是[6,7]

所以基本上我想从第二个数组中取出范围并从第一个数组中删除它们。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

你可以在下面的ES6功能。

它允许您在第一个参数中指定多个范围,并假定它没有重叠范围。函数的返回值是基于第一个参数的数组,但是从第二个参数中指定的范围被删除。在此过程中,原始数组不会发生变异:



function subtractRanges(a, b) {
    // Take deep copy of a and sort it
    a = a.map( x => [...x] ).sort( (x, y) => x[0] - y[0] );
    // Take shallow copy of b and sort it
    b = [...b].sort( (x, y) => x[0] - y[0] );

    var c = [], i = 0, j = 0;
    while (i < a.length && j < b.length) {
        var x = a[i], y = b[j];
        if (y[0] > x[0]) {
            c.push([x[0], Math.min(y[0]-1, x[1])]);
            if (y[1] < x[1]) {
                x[0] = y[1]+1;
                j++;
            } else {
                i++;
            }
        } else {
            if (y[1] >= x[1]) {
                i++;
            } else {
                if (y[1] >= x[0]) {
                    x[0] = y[1]+1;
                }
                j++;
            }
        }
    }
    // Add remainder of a, and return
    return [...c, ...a.slice(i)];
}

// Sample input
var a = [ [1,35] ];
var b = [ [2,5], [8,9] ];

// Get result
var result = subtractRanges(a, b)

// Output result
console.log(JSON.stringify(result));
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您可以使用直接方法检查每个零件范围的范围。它会检查非重叠/重叠部分的每种可能组合。

此提案适用于未分类的数据。

          ----------------                 [ 9, 24] given interval, denotes as r
  0000000001111111111222222222233333333334
  1234567890123456789012345678901234567890 interval result           rules                    return
1         ----------------                 [ 9, 24] none             i[0]===r[0]&&i[0]===r[0] none
2              -------                     [17, 23] [ 9, 16][24, 24] i[0]>r[0]&&i[1]<r[1]     [r[0],i[0]-1][i[1]+1,[r[1]]]
3                     ----------           [21, 30] [ 9, 20]         i[0]>r[0]&&i[0]<r[1]     [r[0],i[0]-1]
4     --------                             [ 5, 12] [13, 24]         i[1]>r[0]&&i[1]<r[1]     [i[1]+1,r[1]]
5 ----                                     [ 1,  4] [ 9, 24]         i[1]<r[0]                r
6                                 -----    [33, 37] [ 9, 24]         i[0]>r[1]                r

function minus(r, a) {
    var newR = [];
    r.forEach(function (b) {
        function push(t) { if (t[0] <= t[1]) { newR.push(t); } }
        var temp = b.slice();
        if (a[0] === b[0] && a[1] === b[1]) { // 1
            return;
        }
        if (a[0] > b[0] && a[1] < b[1]) { // 2
            push([b[0], a[0] - 1]);
            push([a[1] + 1, b[1]]);
            return;
        }
        if (a[0] > b[0] && a[0] < b[1]) { // 3
            temp[1] = a[0] - 1;
        }
        if (a[1] < b[1] && a[1] > b[0]) { // 4
            temp[0] = a[1] + 1;
        }
        push(temp);
    });
    return newR;
}

var ranges = [[1, 35]],
    values = [[2, 5], [8, 9]],
    result = values.reduce(minus, ranges);

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