将两个数组与范围组合

时间:2017-10-11 15:10:39

标签: javascript arrays

我正在尝试组合两个数组。每个阵列都有子阵列,用于定义范围。我想将它组合起来,以便创建的新数组根据两个数组中的值反映新范围。例如:

//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]]

4 个答案:

答案 0 :(得分: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; }




答案 1 :(得分:0)

即使范围没有完全有序且不重叠,此解决方案也能正常工作。

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

答案 2 :(得分:0)

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



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);




答案 3 :(得分:0)

更通用的方法首先展平连接范围列表,其次是这个范围索引列表的排序和唯一变体,最后从中生成范围元组列表。因此,它不依赖于任何范围顺序和/或与范围跨度碰撞无关。

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; }