2

有一个区间数组,需要合并重叠,即:

[[0, 33], [66, 80]] => [[0, 33], [66, 80]]

[[0, 33], [66, 80], [0, 66], [33, 100]] => [0,100]

写了代码。我得到结果 [[0, 100], [66, 80]]。这是因为首先是范围 [[0, 33]],然后是 [[0, 33], [66, 80]] ,然后是 [[0, 66], [66, 80]] ,然后是 [[0, 100 ] , [66, 80]] 好像在不循环的情况下检查其他范围

const data = [
    [0, 33],
    [66, 80],
    [0, 66],
    [33, 100]
  ];

  createDataForSlider = data =>
    data.reduce((prevVal, time) => {
      let isPrevValUpdated = false;

      const timeStart = time[0];
      const timeEnd = time[1];

      /* eslint no-param-reassign: ["error", { "ignorePropertyModificationsFor": ["prevVal"] }] */
      if (prevVal.length) {
        for (let i = 0, ii = prevVal.length; i < ii; i += 1) {
          let prevValCurrent = prevVal[i];

          if (timeStart >= prevValCurrent[0] && timeEnd <= prevValCurrent[1]) {
            isPrevValUpdated = true;
            break;
          }
          if (
            !isPrevValUpdated &&
            timeStart >= prevValCurrent[0] &&
            timeStart <= prevValCurrent[1]
          ) {
            prevValCurrent[1] = timeEnd;
            isPrevValUpdated = true;
            break;
          }
          if (
            !isPrevValUpdated &&
            timeEnd >= prevValCurrent[0] &&
            timeEnd <= prevValCurrent[1]
          ) {
            prevValCurrent[0] = timeStart;
            isPrevValUpdated = true;
            break;
          }

          //console.log("prevVal-", prevVal);
        }
      }
      if (!isPrevValUpdated) {
        prevVal.push([timeStart, timeEnd]);
      }
      return prevVal;
    }, []);

  createDataForSlider(data);
4

5 回答 5

2

尝试关注

  1. 根据所有开始时间对数组进行排序
  2. 现在通过将先前插入的频率与当前频率进行比较,使用空数组累加器来减少它。

    const frequencies = [[0, 33], [66, 80], [0, 66], [33, 100]];
    
    const sortedFrequencies = frequencies.sort((f1, f2) =>{ return f1[0] - f2[0]});
    
    sortedFrequencies.reduce((acc, current) => {
       if(acc.length > 0 && current[0] <= acc[acc.length - 1][1]) {
    
            acc[acc.length - 1][1] = current[1] > acc[acc.length - 1][1] ? current[1] : acc[acc.length - 1][1];
       } else {
    
            acc.push(current)
       }
       return acc;
    }, []);
    
于 2019-01-09T12:31:49.953 回答
0

要合并重叠的一维数组,.sort() 将根据元素 0 处的每个一维数组的升序值对二维数组进行排序。然后,您可以遍历每个元素 - 排序的二维数组的 1 和检查索引 i 处的元素是否是索引 i + 1 处元素的子集。如果是,则将索引 i + 1 处的元素推送到新数组。

function isSubSet(a, b) {
    if ((a[0] >= b[0] && a[1] <= b[1]) ||
        (a[0] <= b[0] && a[1] >= b[1])) {
        return true;
    } else {
        return false;
    }
}

function mergeArray(arr) {

    let newArr = [];

    for (let i = 0; i < arr.length - 1; i++) {
        if (isSubSet(arr[i], arr[i + 1])) {
            newArr.push(arr[i + 1]);
        }
    }

    return newArr;
}

const data = [[0, 33], [66, 80], [0, 66], [33, 100]];

let arr = mergeArray(data.sort());
于 2019-01-09T13:30:41.153 回答
0

您需要先对输入数组进行排序,如下所示:

data.sort((val1, val2) => {
  //order by range start ASC
  let res1 = val1[0] - val2[0];

  if (res1 === 0) {
    //order by range end DESC
    return val2[1] - val1[1];
  }

  return res1;
});

然后它应该工作。

于 2019-01-09T12:37:20.930 回答
0

您可以对数组进行排序(开始 ASC,结束 DESC)并检查开始和结束位置是否在另一个数据集的范围内,然后返回具有最小值和最大值的新集合。否则取原始值。

function merge(array) {
    return array
        .sort((a, b) => a[0] - b[0] || b[1] - a[1])
        .reduce((t, [l, r]) => {
            var item = [[l, r]];
            if (!t) return [[l, r]];
            return t
                .map(([a, b]) =>
                    l <= a && a <= r || l <= b && b <= r || a <= l && l <= b || a <= r && r <= b
                        ? (item = [], [Math.min(a, l), Math.max(b, r)])
                        : [a, b]
                )
                .concat(item);
        }, undefined);
}

console.log(merge([[0, 33], [66, 80], [0, 66], [33, 100]]));
console.log(merge([[0, 33], [66, 80]]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

于 2019-01-09T12:53:39.557 回答
-2

一次又一次地循环,直到输出数组的长度等于输入数组的长度。

如果一轮之后有一些重叠,下一轮将两者合并,输出会更短。

该过程肯定会在少于 data.lenght 的步骤中停止。

从运行时间的角度来看,这不是最有效的方法,但如果这不是问题,我会选择它。

于 2019-01-09T12:07:17.297 回答