4

在 JavaScript 中,给定 n 个数组作为这种格式的输入:(n=2)

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

谢谢你。

4

2 回答 2

3

基准 示例

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

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
            }
        });
    });
}

假设数组已排序并包含x顺序为 1..n 的所有值,没有间隙。

有点需要 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 };
        });
    });
}
于 2011-06-17T08:36:50.827 回答
3

更新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数组,可能更容易跟踪正在进行的总和。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,这是一个“假”值。所以我们使用奇怪强大的||运算符xsum or 中获取它的值0,然后将当前条目添加y到其中并存储结果。

于 2011-06-17T08:41:07.863 回答