我有两个数组,每个数组都有一个Year对象和一个键值对Year和Value.我想创建一个更新版本的array1,将每行年份的值减go array2中相应值的值

即A/FRED/2013应从16减3,减至13,以此类推.

到目前为止,我做到了,但我无法正确更新数组

array1.forEach(r1 => {
    // Get the corresponding row from array2
    let array2Record = array2.find(r2 => r2.key1 === r1.key1 && r2.key2 === r1.key2);
    // Go through each of the years for this row in array1
    Object.entries(r1.years).forEach(keyValuePair => {
        // And reduce it by the value in array2
        keyValuePair.value = keyValuePair.value - array2Record.years[keyValuePair.key].value;
    })
})

这是数据的简化版本

let array1 = [
    {
        "key1": "A",
        "key2": "Fred",
        "years": {
            "2013": 16,
            "2014": 11,
            "2015": 17
        }
    },
    {
        "key1": "A",
        "key2": "Jim",
        "years": {
            "2013": 1,
            "2014": 4,
            "2015": 3
        }
    },
    {
        "key1": "B",
        "key2": "Mary",
        "years": {
            "2013": 1,
            "2014": 4,
            "2015": 3
        }
    }
]

let array2 = [
    {
        "key1": "A",
        "key2": "Fred",
        "years": {
            "2013": 3,
            "2014": 2,
            "2015": 7
        }
    },
    {
        "key1": "A",
        "key2": "Jim",
        "years": {
            "2013": 9,
            "2014": 3,
            "2015": 1
        }
    },
    {
        "key1": "B",
        "key2": "Mary",
        "years": {
            "2013": 8,
            "2014": 3,
            "2015": 6
        }
    }
]

推荐答案

如果你的数据不是很小,你可以更喜欢通过键映射更新数组,然后使用它,从而避免Array::find():

const map = array2.reduce((r, e) => ((r[e.key1] ??= {})[e.key2] = e, r), {});

array1.forEach(e => {
  const found = map[e.key1]?.[e.key2];
  if(!found) return;
  for(const year in e.years){
    e.years[year] -= found.years[year]??0;
  }
});

console.log(array1);
<script>

const array1 = [{"key1":"A","key2":"Fred","years":{"2013":16,"2014":11,"2015":17}},{"key1":"A","key2":"Jim","years":{"2013":1,"2014":4,"2015":3}},{"key1":"B","key2":"Mary","years":{"2013":1,"2014":4,"2015":3}}]
const array2 = [{"key1":"A","key2":"Fred","years":{"2013":3,"2014":2,"2015":7}},{"key1":"A","key2":"Jim","years":{"2013":9,"2014":3,"2015":1}},{"key1":"B","key2":"Mary","years":{"2013":8,"2014":3,"2015":6}}]

</script>

具有3个关键点的示例:

 let array2 = [
    {
        "key1": "A",
        "key2": "Fred",
        key3: 1,
        "years": {
            "2013": 16,
            "2014": 11,
            "2015": 17
        }
    },
    {
        "key1": "A",
        "key2": "Jim",
        key3: 2,
        "years": {
            "2013": 1,
            "2014": 4,
            "2015": 3
        }
    },
    {
        "key1": "B",
        "key2": "Mary",
        key3: 3,
        "years": {
            "2013": 1,
            "2014": 4,
            "2015": 3
        }
    }
]
 
const map = array2.reduce((r, e) => (((r[e.key1] ??= {})[e.key2] ??= {})[e.key3] = e, r), {});

console.log(map);

一个基准更新3名学生从3,30,300和3000名学生(用整数替换名称):

` Chrome/121
-------------------------------------------------------------------------------------
>                   n=3       |      n=30       |      n=300       |      n=3000     
Alexander      1.81x  x1m 168 | 1.00x   x1m 337 |  1.00x x100k 209 |   1.00x x10k 213
Andrew Parks   1.20x  x1m 111 | 3.09x x100k 104 |  4.73x x100k 988 |   5.12x  x1k 109
Onur Dogan     1.00x x10m 928 | 1.60x   x1m 538 | 17.94x  x10k 375 | 206.10x x100 439
-------------------------------------------------------------------------------------
https://github.com/silentmantra/benchmark `

const keys = [...Array(3000).fill().keys()];
keys.forEach((k, i) => {
  const idx = Math.random()*(keys.length-i)|0 + i;
  [keys[i], keys[idx]] = [keys[idx], k];
});
let idx = 0;
const $chunk = () => [{"key1":"A","key2":keys[idx++],"years":{"2013":16,"2014":11,"2015":17}},{"key1":"A","key2":keys[idx++],"years":{"2013":1,"2014":4,"2015":3}},{"key1":"B","key2":keys[idx++],"years":{"2013":1,"2014":4,"2015":3}}]
const array2 = [{"key1":"A","key2":1,"years":{"2013":3,"2014":2,"2015":7}},{"key1":"A","key2":2, "years":{"2013":9,"2014":3,"2015":1}},{"key1":"B","key2":3,"years":{"2013":8,"2014":3,"2015":6}}]

const $input = [];
const array1 = $input;

// @benchmark Andrew Parks

array1.forEach(({key1, key2, years}) => Object.entries(
    array2.find(({key1: a, key2: b}) => a===key1 && b===key2)?.years ?? {}
  ).forEach(([year, count]) => years[year] -= count)
)
array1;

// @benchmark Onur Dogan

array1.concat(array2).reduce((tot, val) => { 
const index = tot.findIndex(({ key1, key2 }) => key1 === val.key1 && key2 === val.key2);

if(index > -1){
  Object.keys(val.years).forEach(yearKey => {
    tot[index].years[yearKey] -= val.years[yearKey];
  });
}
else {
    tot.push(val);
}

   return tot;
}, []);

// @benchmark Alexander

const map = array2.reduce((r, e) => ((r[e.key1] ??= {})[e.key2] = e, r), {});

array1.forEach(e => {
  const found = map[e.key1]?.[e.key2];
  if(!found) return;
  for(const year in e.years){
    e.years[year] -= found.years[year]??0;
  }
});
array1;

/*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));

Javascript相关问答推荐

从连接字符串创建客户端时,NodeJS连接到CosmosDB失败

React:未调用useState变量在调试器的事件处理程序中不可用

为什么我的includes声明需要整个字符串?

传递一个大对象以在Express布局中呈现

Angular material 拖放堆叠的牌副,悬停时自动展开&

Promise Chain中的第二个useState不更新

使用Java脚本根据按下的按钮更改S文本

如何在ASP.NET JavaScript中使用Google Charts API仅对绘制为负方向的条形图移动堆叠条形图标签位置

JavaScript不重定向配置的PATH

面对代码中的错误作为前端与后端的集成

为什么可选参数的顺序会导致问题?

按下单键和多值

如何在Java脚本中对列表中的特定元素进行排序?

Cherrio JS返回父div的所有图像SRC

我不知道如何纠正这一点.

我怎样才能得到一个数组的名字在另一个数组?

在没有任何悬停或其他触发的情况下连续交换图像

我无法在Api Reaction本机上发出GET请求

表单数据中未定义的数组键

在传单的图像覆盖中重新着色特定 colored颜色 的所有像素