创建一个地图回调,以按数组总和

时间:2016-08-18 21:24:54

标签: javascript arrays

我的目标是编写一个回调函数......

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]

我希望这是......

  • 自包含 - 我不想提前计算总和
  • 高效 - 我不想在每次迭代时重新计算总和
  • 可与其他fn 互换< - > - 见下文编辑

这个问题非常简单没有那些标准。即使有这三个标准,我仍然认为有一些简单/明显的方法可以做到这一点(或许类似于尝试&#34;保存&#34;每次迭代中常见的一些闭包中的总和),但由于某种原因我画了一个空白。有什么想法吗?

测试工作答案......

let arr = [1,2,3],
    callbacks = [Math.sqrt, Math.round, Math.sin, **proportionalize**, etc...];

for(cb in callbacks){
  console.log(arr.map(callbacks[cb]))
}

修改

此外,作为参考,有一个非答案,&#34;工作&#34;,但我会考虑一个非答案,因为它需要将一个参数传递给一个函数然后生成回调。我希望调用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)

3 个答案:

答案 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应用于数组的每个元素。它不是对阵列本身的操作,而是对其元素的操作。

虽然这不是&#34;地图回调&#34;,但您现有的解决方案可能如下所示:

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