Javascript - 求解2维数组的和

4

我有两个二维数组

var arr1 = [
  [1, 'a'],
  [2, 'b']
]

var arr2 = [
  [3, 'a'],
  [5, 'c']
]

我想将这两个数组相加,得到以下结果。
var output = [
  [4, 'a'],
  [2, 'b'],
  [5, 'c']
]

我尝试编写了两个.map函数,但是除了期望的结果之外,它还会返回很多重复项:

function sumArrays (arr1, arr2) {
  var output = [];
  arr2.map(function(i) {
    arr1.map(function(n) {
      if (i[1] === n[1]) {
        output.push([i[0] + n[0], i[1]])
      } else {
        output.push(i)
      }
    })
  })
  return output;
}

有没有更简单的方法来做这件事,或者我现在应该删除除特定字符串以外的所有内容,只保留最高值?

感谢您的帮助。


你想要一个新的数组来合并结果吗? - Nina Scholz
我需要返回这两个数组的总和。我可以通过修改现有数组来实现,也可以返回一个新数组。 - Miha Šušteršič
使用地图会更容易,例如 {a : 4, b : 2, c : 5} - adeneo
arr1.concat(arr2).reduce((a,b)=>{return b[1] in a?a[b[1]]+=b[0]:a[b[1]]=b[0],a;},{}); - adeneo
4个回答

3
请勿使用 Array#map,除非您不需要新的数组(该方法会返回一个新数组)。
您可以使用哈希表来管理库存,并使用 Array#forEach 来检查和更新 arr2
建议使用 arr1 进行更新。

var arr1 = [[1, 'a'], [2, 'b']],
    arr2 = [[3, 'a'], [5, 'c']],
    inventory = Object.create(null);

arr1.forEach(function (a) {
    this[a[1]] = a;
}, inventory);

arr2.forEach(function (a) {
    if (!this[a[1]]) {
        this[a[1]] = [0, a[1]];
        arr1.push(this[a[1]]);
    }
    this[a[1]][0] += a[0];
}, inventory);

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

使用新数组 result 的建议。

var arr1 = [[1, 'a'], [2, 'b']],
    arr2 = [[3, 'a'], [5, 'c']],
    inventory = Object.create(null),
    result = arr1.map(function (a) {
        return this[a[1]] = [a[0], a[1]];
    }, inventory);

arr2.forEach(function (a) {
    if (!this[a[1]]) {
        this[a[1]] = [0, a[1]];
        result.push(this[a[1]]);
    }
    this[a[1]][0] += a[0];
}, inventory);

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


2
控制台的技巧不错。 - zer00ne
好的解释。但是,期望的结果是一个数组,那为什么不使用一个数组呢? - Pranesh Ravi
@PraneshRavi,结果是一个数组,你在哪里看不到数组? - Nina Scholz
错别字!为什么不使用map()函数? - Pranesh Ravi
你是指 Map 吗?ES6? - Nina Scholz

0

这个问题本质上与这个相同,我建议使用相同的ES6代码,使用哈希(Set)和一些变体代码,这里不再重复:

function sumArrays(a, b) {
    return Array.from(
        b.reduce( (m, [v,k]) => m.set(k, (m.get(k) || 0) + v),
                   new Map(a.map ( ([v,k]) => [k,v] )) ), // swap pairs
        ([k,v]) => [v,k]) // swap back afterwards;
}

var arr1 = [
  [1, 'a'],
  [2, 'b']
]

var arr2 = [
  [3, 'a'],
  [5, 'c']
]

var result = sumArrays(arr1, arr2);

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


0
你还可以使用forEach()findIndex()来完成这个操作。

var arr1 = [
  [1, 'a'],
  [2, 'b']
]

var arr2 = [
  [3, 'a'],
  [5, 'c']
]

function sumArrays(arr1, arr2) {
  var r = arr1.slice(0);
  arr2.forEach(function(e) {
    var i = arr1.findIndex(function(a) {
      return e[1] == a[1];
    })
    i != -1 ? r[i][0] += e[0] : r.push(e)
  })
  return r;
}

console.log(sumArrays(arr1, arr2))


0

将这两个数组连接起来,这样你就有了一个包含所有元组的数组。

然后减少元组数组的大小,使得任何兼容的元组都被累积。

arr1.concat(arr2).reduce(function r(accumulator, iterand) {

    // base case: no tuples in accumulator
    if (accumulator.length == 0) {
        // add current tuple to our empty accumulator.
        return [iterand];
    }

    // first tuple in accumulator is compatible with the currently-inspected tuple
    if (accumulator[0][1] == iterand[1]) {
        // increment the count in the compatible tuple that already exists in the accumulator
        return [[accumulator[0][0]+iterand[0], accumulator[0][1]]].concat(accumulator.slice(1));
    }

    // currently-inspected tuple is not compatible with first tuple in accumulator. leave first tuple in accumulator unchanged. run the inductive case upon the remaining tuples in the accumulator.
    return [accumulator[0]].concat(r(accumulator.slice(1), iterand));

}, [])

这是一个功能性的解决方案,不会改变您现有的任何输入数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接