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

更新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 - 1から0(または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ない場合は、「falsey」の値になります。そのため、不思議なことに強力な演算子を使用して、またはからその値を取得し、それに現在のエントリを追加して結果を保存します。xsum[entry.x]undefined||xsum 0y

于 2011-06-17T08:41:07.863 に答える
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
            }
        });
    });
}

配列がソートされており、すべての値がx1..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 に答える