我的目标是编写一个回调函数......
function proportionize(val,ind,arr){
...
}
这样当提供给Array.prototype.map时,返回数组中的每个值都是数组总数的相应比例。
例如,
let myArray = [1,2,3] // Sums to 6
let proportions = myArray.map( proportionalize ) // [1/6, 2/6, 3/6]
我希望这是......
这个问题非常简单没有那些标准。即使有这三个标准,我仍然认为有一些简单/明显的方法可以做到这一点(或许类似于尝试"保存"每次迭代中常见的一些闭包中的总和),但由于某种原因我画了一个空白。有什么想法吗?
测试工作答案......
let arr = [1,2,3],
callbacks = [Math.sqrt, Math.round, Math.sin, **proportionalize**, etc...];
for(cb in callbacks){
console.log(arr.map(callbacks[cb]))
}
修改
此外,作为参考,有一个非答案,"工作",但我会考虑一个非答案,因为它需要将一个参数传递给一个函数然后生成回调。我希望调用map以匹配任何其他函数的调用。例如......
// The "working" non-answer
function proportionalize(arrIn){
let total = arrIn.reduce( (a,b)=>a+b);
return (val,ind,arr)=>{ return val/total };
}
myArray.map(proportionalize(myArray)) // works but I'd have to call differently than...
myArray.map(Math.sqrt)
答案 0 :(得分:0)
这个答案有效,但有一些我不喜欢的事情......
方法:
arr.total
(每次迭代都可用)arr.total
total
属性
代码:
function proportionalize(val, ind, arr){
if(ind===0){
arr.total = arr.reduce( (a,b)=>a+b);
}
let proportion = val/arr.total;
if(ind===(arr.length-1)){
delete arr.total;
}
return proportion;
}
[1,2,3].map(proportionalize) // [ 0.16666666666666666, 0.3333333333333333, 0.5 ]
我不喜欢的内容:
我正在修改数组,添加和删除“total”属性。一般来说,我不想假设该属性尚未用于其他内容。该属性名称可以更改为随机字母或其他字符串,但仍然感觉有点hacky。
答案 1 :(得分:0)
请记住,[1,2,3].map(proportionalize)
将proportionalize
应用于数组的每个元素。它不是对阵列本身的操作,而是对其元素的操作。
虽然这不是"地图回调",但您现有的解决方案可能如下所示:
Array.prototype.proportionalize = function() {
let sum = this.reduce((a,b) => a+b);
return this.map(x => x/sum);
}
例如:
> [1,2,3].proportionalize()
[ 0.16666666666666666, 0.3333333333333333, 0.5 ]
答案 2 :(得分:0)
这个问题可能更普遍地被问为......,
当我使用给定的回调函数调用map时,如何在回调函数的每个实例/调用之间创建/利用共享状态?。一旦回答了这个问题,您就可以使用短路评估之类的东西来防止计算被不必要地重复。
我发现Array.prototype.map已经为可选thisArg
提供了此功能。如果尚未使用this
,则提供空对象{}
允许回调调用修改/共享相同的this
,而不修改超出地图生命周期的状态调用
从这个空状态开始,只有在没有计算总数并且每次迭代都可以访问总数时,才计算总数。
proportionalize = function(val, ind, arr){
this.total = this.total || arr.reduce((x,y)=>x+y);
return val/this.total;
}
let arr = [1,2,3],
callbacks = [Math.round, proportionalize];
for(cb in callbacks){
console.log(arr.map(callbacks[cb],{}))
// => [1,2,3], [ 0.16666666666666666, 0.3333333333333333, 0.5 ]
}
arr = [1,2,7];
for(cb in callbacks){
console.log(arr.map(callbacks[cb],{}))
// => [1,2,3], [ 0.1, 0.2, 0.7 ]
}