我有一个看起来像这样的数组数组:
changes = [ [1, 1, 1, -1], [1, -1, -1], [1, 1] ];
我想通过添加最后一个值来获取数组中的下一个值
values = [ [1, 2, 3, 2], [1, 0, -1], [1, 2] ];
到目前为止,我已经尝试使用forEach:
changes.forEach(change => {
let i = changes.indexOf(change);
let newValue = change[i] + change[i + 1]
});
我认为我做对了,但是我无法采用这种方法工作,或者也许有更好的方法来实现它。
答案 0 :(得分:23)
您可以保存总和并添加值。
var array = [[1, 1, 1, -1], [1, -1, -1], [1, 1]],
result = array.map(a => a.map((s => v => s += v)(0)));
console.log(result);
使用forEach
,您需要获取对象引用以及前一个值或零。
var array = [[1, 1, 1, -1], [1, -1, -1], [1, 1]];
array.forEach(a => a.forEach((v, i, a) => a[i] = (a[i - 1] || 0) + v));
console.log(array);
答案 1 :(得分:13)
带有map的版本。
const changes = [
[1, 1, 1, -1],
[1, -1, -1],
[1, 1]
];
const values = changes.map(array => {
let acc = 0;
return array.map(v => acc += v);
});
console.log(values);
.as-console-wrapper{top:0;max-height:100%!important}
这不会更改源数组。
答案 2 :(得分:4)
生成器的新ESNext功能对此非常有用。
在这里,我已经创建了一个简单的sumpUp
生成器,可以重复使用。
function* sumUp(a) {
let sum = 0;
for (const v of a) yield sum += v;
}
const changes = [ [1, 1, 1, -1], [1, -1, -1], [1, 1] ];
const values = changes.map(a => [...sumUp(a)]);
console.log(values);
答案 3 :(得分:3)
您可以使用Array的map函数
const changes = [ [1, 1, 1, -1], [1, -1, -1], [1, 1] ];
const result = changes.map((v) => v.slice(0).map((t, i, arr) => i === 0 ? t : (arr[i] += arr[i - 1])))
console.log(changes);
console.log(result);
使用slice克隆数组。这将防止更改原始阵列。
答案 4 :(得分:3)
const changes = [ [1, 1, 1, -1], [1, -1, -1], [1, 1] ]
let values = []
changes.forEach(arr => {
let accu = 0
let nestedArr = []
arr.forEach(n => {
accu += n
nestedArr.push(accu)
})
values.push(nestedArr)
})
console.log(values)
答案 5 :(得分:2)
另一种方式
您可以使用.map
返回具有所需结果的新数组。通过将.reduce
与数组作为累加器,可以生成子数组。
var array = [[1, 1, 1, -1], [1, -1, -1], [1, 1]],
result = array.map(a => a.reduce((ac, v, i) => {
const lastVal = ac[i-1] || 0;
return [...ac, lastVal + v];
}, []));
console.log(result);
// shorter
result = array.map(a => a.reduce((ac, v, i) => [...ac, (ac[i-1] || 0) + v], []));
console.log(result);
答案 6 :(得分:2)
这是遍历数组外部列表的一种更易于阅读的方式。创建内部数组的副本以保留初始值(例如[1、1、1、1 -1])。然后,它将遍历复制数组中的每个值,并将其添加到原始数组中的每个索引之后。
var changes = [[1, 1, 1, -1], [1, -1, -1], [1, 1]];
changes.forEach(subArray => {
var subArrayCopy = subArray.slice(); // Create a copy of the current sub array (i.e. subArrayCopy = [1, 1, 1, -1];)
subArrayCopy.forEach((val, index) => { // Iterate through each value in the copy
for (var i = subArray.length - 1; i > index; i--) { // For each element from the end to the current index
subArray[i] += val; // Add the copy's current index value to the original array
}
});
})
console.log(changes);
答案 7 :(得分:0)
您有一个数组数组,但是每个组成数组都与下一个数组无关,因此让我们单独解决它们。让我们来谈谈[1, 1, 1, -1]
。
您使用的“部分和”一词非常有用。 全额可以使用reduce
来实现:
[1, 1, 1, -1].reduce((x, y) => x + y);
// 2
但是您需要一个部分和数组。这与reduce
的用法非常相似,但是我们不仅保留了最后的计算结果,还保留了每个中间值。在其他语言中,这称为scan
(参见F#,Haskell)。
通用scan
的javascript实现看起来很像reduce
。实际上,您可以使用reduce
来实现它,而只需做一些额外的工作:
function scan(array, callback) {
const results = [array[0]];
// reduce does all the heavy lifting for us, but we define a wrapper to pass to it.
array.reduce((...args) => {
// The wrapper forwards all those arguments to the callback, but captures the result...
const result = callback(...args);
// ...storing that intermediate result in our results array...
results.push(result);
// ...then passes it back to reduce to continue what it was doing.
return result;
});
return results;
}
// scan([1, 1, 1, -1], (x, y) => x + y) -> [1, 2, 3, 2]
更健壮的实现会更接近于标准库的reduce
,尤其是在初始值附近:
function scan(array, callback, initialValue) {
const results = [];
const reducer = (...args) => {
const result = callback(...args);
results.push(result);
return result;
};
if (arguments.length === 2) {
results.push(array[0]);
array.reduce(reducer);
} else {
results.push(initialValue);
array.reduce(reducer, initialValue);
}
return results;
}
将其重新组合在一起,如果您要对数组数组执行此操作,那么它就只是map
上的scan
:
[[1, 1, 1, -1], [1, -1, -1], [1, 1]].map(a => scan(a, (x, y) => x + y));
// [[1, 2, 3, 2], [1, 0, -1], [1, 2]]
无需复制,也无需注意副作用,因此您可以从中获得方便的高阶功能来启动!