3

在JavaScript中,给定的阵列作为输入以这种格式的n个:(N = 2)聚合JavaScript数组的对象值?

array1: 
[{x: 1, y: 5},{x: 2, y: 3},{x: 3, y: 6}] 

array2: 
[{x: 1, y: 2},{x: 2, y: 6},{x: 3, y: 2}] 

如何容易聚集的Y值,并获得该结果数组:

arrayOutput: 
[{x: 1, y: 7},{x: 2, y: 9},{x: 3, y: 8}] 

谢谢。

+0

你能给我们提供更多关于价值的信息吗?例如,在你的例子中,每个数组的条目都有唯一的“x”值(例如,同一个'x'不出现在同一个数组中)。这有保证吗? “x”是决定是否合并“y”值的决定因素,还是数组中的位置?像这样的东西。 – 2011-06-17 08:33:30

+0

@ T.J。 Crowder:你可以假设所有的数组具有相同的长度,并且具有相同的唯一x值。数组的个数将会非常大,所以一个有效的函数将非常有用。谢谢。 – dani 2011-06-17 08:36:52

+0

啊,好吧,那改变了事情。 – 2011-06-17 08:41:45

回答

2

更新:关于阵列中的x价值观和他们的立场额外的评论使得下面无关。

没有特别的窍门,你只需循环访问数组并建立结果。它只不过是一个嵌套循环。如果您想在各种JavaScript引擎中达到最高效率,请避免不必要的函数调用。

东西沿着线:

function sumYValues(arrays) { 
    var outer, inner, array, entry, sum, result, x; 

    // Create our result array with a copy of the first array 
    result = []; 
    if (arrays.length > 0) { 
     array = arrays[0]; 
     for (inner = 0; inner < array.length; ++inner) { 
      entry = array[inner]; 
      result[inner] = {x: entry.x, y: entry.y}; 
     } 

     // Add in the remaining values 
     for (outer = 1; outer < arrays.length; ++outer) { 
      array = arrays[outer]; 
      // You might want an assert here verifying that result.length == array.length 
      for (inner = 0; inner < array.length; ++inner) { 
       entry = array[inner]; 
       // You might want an assert here verifying that result[inner].x == entry.x 
       result[inner].y += entry.y; 
      } 
     } 
    } 

    return result; 
} 

这些环从0(或1)数到array.length - 1。你可能会描述是否后退(array.length - 10(或1))更快,主要是“下降到0”。我曾经以为这是因为它是在C时,我是一个新鲜的年轻人(比较0比比较另一个变量更快),但是这个假设可能有效或不可能在JavaScript中有效。


没有特别的捷径,您只需循环访问数组,进行比较并建立结果。

如果x值在每个数组中都是唯一的,则可以更容易地使用对象而不是数组来跟踪您正在进行的总和,并将其作为关键字使用,然后将它转换为数组'重做。例如为:

function sumYValues(arrays) { 
    var outer, inner, ar, entry, sum, result, x; 

    sum = {}; 
    for (outer = 0; outer < arrays.length; ++outer) { 
     ar = arrays[outer]; 
     for (inner = 0; inner < arrays.length; ++inner) { 
      entry = ar[inner]; 
      sum[entry.x] = (sum[entry.x] || 0) + entry.y; 
     } 
    } 

    result = []; 
    for (x in sum) { 
     result.push({x: x, y: sum[x]}); 
    } 

    return result; 
} 

以上是大多只是说明使用sum,对象,作为地图上x =>y值,虽然它确实实现至少一些所述求和逻辑的为好。

该行可能需要一些解释:

  sum[entry.x] = (sum[entry.x] || 0) + entry.y; 

如果sum没有为x值的条目,sum[entry.x]undefined,这是一个“falsey”值。因此,我们使用curiously-powerful || operator或者从sum0获取x的值,然后将当前条目的y添加到它并存储结果。

+0

非常感谢你:)我也会检查剖析方面。 – dani 2011-06-17 09:04:08

+1

J.Crowder [Benchmark](http://jsperf.com/underscore-vs-manual/3)。 'inner Raynos 2011-06-17 09:33:29

+0

@TJCrowder是它变成了噪音。 (清理它)@dani在优化方面,本地方法创建新的对象。如果你想要一个新的数组(比如返回的数组)使用本地方法。如果你不需要一个新的对象,那么使用/ while循环来编辑内存中的数组。 – Raynos 2011-06-17 14:46:14

3

Benchmark Example

注意,混合码速度更快,然后循环,然后本地/下划线。

function createOutput(arr1, arr2, arr3 /*, ... */) { 
    return Array.prototype.reduce.call(arguments, function (prev, curr) { 
     return prev.map(function(val, index) { 
      return { 
       x: val.x, 
       y: val.y + curr[index].y 
      } 
     }); 
    }); 
} 

假定阵列排序,并包含在顺序1..n的,没有空位的x所有值。

种类需要ES5。这可以换成_,它以跨浏览器的方式提供这种功能。

以下划线是

function createOutput() { 
    return _.reduce(arguments, function (memo, arr) { 
     return _.map(memo, function(val, index) { 
      return { x: val.x, y: val.y + arr[index].y }; 
     }); 
    }); 
} 
+0

我认为这不符合“高效”测试。这是l33t,但它是一个*巨大数量的函数调用,并且你要做的第一件事就是创建一个“非常大数量的数组”的副本。 :-) – 2011-06-17 08:51:32

+0

@ T.J.Crowder是的,副本是不必要的,因为'_'无论如何。它仍然是'O(N)'。是的,有开销,但它是简洁和高水平。我确定Google的封闭编译器可以将效率低下的数据分解掉。 – Raynos 2011-06-17 09:09:54

+1

@TJCrowder它实际上赢得了“高效”测试;) – Raynos 2011-06-17 10:06:26