【问题标题】:Combine two arrays with ranges将两个数组与范围组合
【发布时间】:2017-10-12 02:29:00
【问题描述】:

我正在尝试合并两个数组。这些数组中的每一个都有定义范围的子数组。我想将它组合起来,以便创建的新数组反映基于两个数组中的值的新范围。示例:

//I would like to create a new array based on the ranges in a and b.
var a = [[0, 20], [20, 40], [40, 70]];
var b = [[10, 25], [25, 35]]

//The result reflects the new ranges based on values in both the arrays.
var result = [[0, 10], [10, 20], [20, 25], [25, 35], [35, 40], [40, 70]]

【问题讨论】:

  • 你能发布你的代码吗?
  • 是否保证订购范围?也可以,请发布您的尝试。
  • 是的。他们需要订购。我尝试做一个 switch case 语句,但它变得笨拙。所以那没有用。我正在尝试另一种方法。我会尽快发布。谢谢大家
  • 您的问题没有多大意义,您能详细说明一下吗?另请阅读stackoverflow.com/help/how-to-ask 和 MCVE。如果您不向我们展示任何代码,您希望我们如何帮助您解决问题?

标签: javascript arrays


【解决方案1】:

您可以收集对象中的所有值,对其进行排序并从中构建元组。

var a = [[0, 20], [20, 40], [40, 70]],
    b = [[10, 25], [25, 35]],
    values = Object.create(null),
    result = [];

a.concat(b).forEach(function (a) {
    values[a[0]] = true;
    values[a[1]] = true;
});

Object
    .keys(values)
    .map(Number)
    .sort(function (a, b) {
        return a - b;
    })
    .reduce(function (a, b) {
        result.push([a, b]);
        return b;
    });

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

【讨论】:

    【解决方案2】:

    即使范围不是完全有序且不重叠,此解决方案也有效。

    1. 将两个列表合并为一个数组数组
    2. 将数组数组扁平化为一个简单的数字数组
    3. 从数组中删除重复项(除第一个和最后一个之外的每个数字都包含两次,因此我们需要修复它)
    4. 遍历扁平化和重复数据删除的数组
    5. 找到最小值的索引,然后从数组中删除最小值
    6. 将该最小值添加到代表单个范围的“temp_range”中
    7. 如果“temp_range”的长度现在是 2,我们将其添加到最终的范围数组中,然后让 temp_range 以当前的最小值开始

     
    
        var a = [[0, 20], [20, 40], [40, 70]];
        var b = [[10, 15], [25, 35]]
        var combined = a.concat(b);
        var flattened = combined.reduce((a, b) => a.concat(b), []);
        flattened = flattened.filter(function(item, pos) {
            return flattened.indexOf(item) == pos;
        });
        var final_array = [];
        var temp_range = [];
        var minIdx = null; 
        var minVal = null;
        while (flattened.length){
           minIdx = flattened.indexOf(Math.min(...flattened));
           minVal = flattened.splice(minIdx, 1)[0];
           temp_range.push(minVal);
           if(temp_range.length == 2){
             final_array.push(temp_range);
             temp_range = [minVal];
           }
        }
        console.log(final_array);
       

    【讨论】:

    • 这很棒。正是我需要的。谢谢
    【解决方案3】:

    一种更通用的方法首先将连接的范围列表展平,然后对该范围索引列表进行排序且唯一的变体,最后从中生成范围元组列表。因此,它不依赖于任何范围顺序和/或不知道范围跨度冲突。

    function flatten(list) { // simplified variant
      if (Array.isArray(list)) {
        list = list.reduce(function (collector, elm) {
    
          return collector.concat(flatten(elm));
    
        }, []);
      }
      return list;
    }
    
    function unique(list) { // simplified variant
      var i = -1, k, len = list.length, type;
    
      while (++i < len) {
        type = list[i];
        k = i;
    
        while ((i in list) && (++k < len)) {
          if ((k in list) && (list[k] === type)) {
    
            list.splice(k, 1);
            --len;
            --k;
          }
        }
      }
      return list;
    }
    
    var aRangeList = [[0, 20], [20, 40], [40, 70]];
    var bRangeList = [[10, 25], [25, 35]];
    
    var cRangeList = unique(
    
      flatten(aRangeList.concat(bRangeList)).sort()
    
    ).reduce(function collectRangeTuple (collector, rangeIndex) {
      var tuple = collector.recentTuple;
    
      tuple.push(rangeIndex);
    
      if (tuple.length >= 2) {
        collector.rangeList.push(tuple);
        collector.recentTuple = [rangeIndex];
      }
      return collector
    
    }, { recentTuple: [], rangeList: [] }).rangeList;
    
    console.log('aRangeList : ', aRangeList);
    console.log('bRangeList : ', bRangeList);
    console.log('cRangeList : ', cRangeList);
    .as-console-wrapper { max-height: 100%!important; top: 0; }

    【讨论】:

      【解决方案4】:

      虽然我喜欢发布的其他更实用的方法,但我不喜欢它依赖于定义事物的副作用的事实。这是一个稍微改进的版本。

      var a = [[0, 20], [20, 40], [40, 70]];
      var b = [[10, 25], [25, 35]];
      
      // Utility function for flattening the input arrays
      var flatten = function flatten(arr) {
        return arr.reduce(function(agg, arr) {
          return agg.concat(Array.isArray(arr) ? flatten(arr) : arr);
        }, []);
      };
      
      // Combine everything into a single flat list of numbers
      var c = flatten(a.concat(b));
      
      // Create a hash out of the values to get unique endpoints
      var d = c.reduce(function(agg, n) {
        agg[n] = true;
        return agg;
      }, {});
      
      // Reduce the hash to the ranges
      var [_, e] = Object.keys(d).map(Number).reduce(function([last, agg], n) {
        if(last === null) return [n, agg];
        agg.push([last, n]);
        return [n, agg];
      }, [null, []]);
      
      console.log(e);

      【讨论】:

        猜你喜欢
        • 2016-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-30
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 2015-05-26
        相关资源
        最近更新 更多