【问题标题】:Multidimensional array replace with close range Javascript多维数组替换为近距离 Javascript
【发布时间】:2021-12-04 20:46:10
【问题描述】:

假设我们有一个 List 以数组形式表示的范围,其中包含两个元素 [from, to]

当我们添加一个像[5,8]这样的新数组范围时,它应该检查List中是否有最接近的范围,然后用新的范围值替换它。下面提供了一个示例:

示例 1

var List = [[1,2], [3,4], [6,7], [9,10]]

var newData = [5,8]

预期输出:

[[1,2], [3,4], [5,8], [9,10]]

[6,7] 范围已包含在 [5,8]

示例 2

var List = [[1,3], [4,6], [8,10]]
var newData = [5,9]

预期输出:

[[1,3], [4,10]]

【问题讨论】:

  • 在初始列表[[1,2], [3,4], [6,7], [9,10]] 中,前两个范围似乎可以合并:[[1,4], [6,7], [9,10]]。这是疏忽吗?

标签: javascript arrays multidimensional-array


【解决方案1】:

假设初始列表格式正确,其对已排序且不重叠,您可以使用二分搜索在数组中找到新对的端点,从而确定任何重叠。如果重叠,则对数组进行相应的拼接:

function addSegments(segments, ...pairs) {
    for (let pair of pairs) {
        let [start, end] = pair.map(function (x, i) { // Binary search
            let low = 0, 
                high = segments.length;
                side = 1 - i;
            while (low < high) {
                let mid = (low + high) >> 1;
                if (x < segments[mid][side]) high = mid;
                else low = mid + 1;
            }
            return low - (side && segments[low-1]?.[side] === x);
        });
        if (start < end) {
            pair = [
                Math.min(segments[start][0], pair[0]),
                Math.max(segments[end-1][1], pair[1])
            ];
        }
        segments.splice(start, end - start, pair);
    }
}

// Demo
let list = [[1, 2], [3, 4], [6, 7], [9, 10]];
addSegments(list, [5, 8]);
console.log(JSON.stringify(list));

list = [[1, 3], [4, 6], [8, 10]];
addSegments(list, [5, 9]);
console.log(JSON.stringify(list));

【讨论】:

    【解决方案2】:

    如果我们有两个数组包含范围内的所有整数,那么我们可以相交并查看它们是否重叠。如果是这样,我们会根据两个范围的并集创建一个新范围,并在输出中使用它。

    为此,我们定义了三个辅助函数 range()、intersect() 和 union(),然后我们使用它们来生成输出数组。如果存在交集,我们用两者的新并集覆盖任何重叠的范围。我假设如果两个范围刚刚接触,它们并不意味着要合并,所以只有在交叉点包含多个元素时才会触发覆盖。另外,我添加了一个初始排序。

    function add(list, data) {
      
      let buffer = [], idx;
      const range=(a,b)=>Array.from({length:b-a+1}, (_, i)=>(a+i));
      const intersect=(a,b)=>a.filter(x=>b.includes(x));
      const union=(a,b)=>[...new Set([...a, ...b])].sort((a,b)=>a-b);
      list.sort((a,b)=>a[0]-b[0]);
      
      list.forEach(el=>{
        
        let x = range(el[0], el[1]);
        let y = range(data[0], data[1]);
        let i = intersect(x, y);
        
        if(i.length>1) {
          let d = union(x,y);
          data = [d[0], d[d.length-1]];
          if(idx) { buffer[idx] = data; }
          else { idx = buffer.push(data)-1; }
        } 
        else { buffer.push(el); };
        
      });
      
      return buffer;
      
    }
    
    
    // DEMO
    let List = [[1,2], [3,4], [6,7], [9,10]];
    let newData = [5,8];
    console.log(JSON.stringify(List));
    console.log(JSON.stringify(newData));
    console.log(JSON.stringify(add(List, newData)));
    console.log('');
    
    List = [[1,3], [4,6], [8,10]];
    newData = [5,9];
    console.log(JSON.stringify(List));
    console.log(JSON.stringify(newData));
    console.log(JSON.stringify(add(List, newData)));
    console.log('');
    
    // DEMO WITH UNORDERED ELEMENTS
    List = [[3,4], [9,10], [6,7], [1,2]];
    newData = [5,8];
    console.log(JSON.stringify(List));
    console.log(JSON.stringify(newData));
    console.log(JSON.stringify(add(List, newData)));
    console.log('');

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      相关资源
      最近更新 更多