0

ピンチで書いたJavaScriptがいくつかありますが、私より賢い誰かがそれを大幅に最適化できると思います。このコードは比較的小さなオブジェクトで実行されますが、かなりの回数実行されるため、適切に処理する価値があります。

/**
 *  Determine the maximum quantity we can show (ever) for these size/color combos
 *
 *  @return int=settings.limitedStockThreshold
 */
function getMaxDefaultQuantity() {
    var max_default_quantity = 1;

    if (inventory && inventory.sizes) {
        sizecolor_combo_loop:
        for (var key in inventory.sizes) {
            if (inventory.sizes[key].combos) {
                for (var key2 in inventory.sizes[key].combos) {
                    var sizecolor_combo = inventory.sizes[key].combos[key2];
                    if (isBackorderable(sizecolor_combo)) {
                    //if even one is backorderable, we can break out
                        max_default_quantity = settings.limitedStockThreshold;
                        break sizecolor_combo_loop;
                    } else {
                    //not backorderable, get largest quantity (sizecolor_combo or max_default_quantity)
                        var qoh = parseInt(sizecolor_combo.quantityOnHand || 1);
                        if (qoh > max_default_quantity) {
                            max_default_quantity = qoh;
                        };
                    };
                };
            };
        };
    };

    return Math.min(max_default_quantity, settings.limitedStockThreshold);
};

まず、在庫は JSON 経由で返されるオブジェクトです。商品の利用可能なすべてのサイズを含むプロパティinventory.sizesがあります。各サイズには、サイズで使用可能なすべての色にマップされるプロパティinventory.sizes.combosがあります。各コンボには、その特定のコンボで利用可能な数量を伝えるプロパティquantityOnHandもあります。(返される JSON 構造は変更できません)

コードが行うことは、各サイズをループしてから、各サイズのコンボをループすることです。次に、サイズと色の組み合わせが (別の方法で) 取り寄せ可能かどうかを確認します。取り寄せ可能なコンボがある場合は、デフォルトの数量が別の場所で定義されているため、停止できます。コンボが取り寄せ可能でない場合、max_default_quantity は、見つけた最大の quantityOnHand です (settings.limitedStockThreshold の最大数)。

ネストされた for ループが本当に好きではなく、数学とデフォルト値の処理が複雑すぎるように感じます。

また、クリーンアップに役立つ場合は、この関数全体がはるかに大きな jQuery オブジェクトにラップされます。

4

2 に答える 2

0

残念ながら、古いブラウザをサポートする必要がある場合、JavaScript には洗練されたコレクション処理機能があまりないため、追加のライブラリの助けがなければ、作成したようなネストされたループが使用されます。同じ計算を何度も実行する必要がないように、代わりに値をサーバー側で事前に計算し、おそらくキャッシュし、それを JSON に含めることを検討できます。

于 2011-01-26T00:15:49.357 に答える
0

map-reduce の使用を検討しましたか? 関数型アプローチの実例をご覧ください。

この特定の例ではunderscore.jsを使用しているため、詳細を実装しなくてもエレガントなレベルに保つことができます。

function doStuff(inventory) {
    var max = settings.limitedStockThreshold;
    if (!(inventory && inventory.sizes)) return;

    var quantity = _(inventory.sizes).chain()
        .filter(function(value) {
            return value.combos;
        })
        .map(function(value) {
            return _(value.combos).chain()
                .map(function(value) {
                    return isBackorderable(value) ? max : value.quantityOnHand;
                })
                .max().value();
        })
        .max().value();

    return Math.min(quantity, max);
}

説明については:

inventory.sizes セットを取得し、コンボを含まないものをすべて削除します。次に、各サイズをその色の最大量にマッピングします。各コンボをその数量またはバックオーダー可能な場合は最大数量にマッピングします。次に、そのセットの最大値を取得します。

最後に、サイズごとに maxQuantities の最大セットを取得します。

セットで2 つの for ループを使用しているため、効果的に二重の for ループを実行.maxしていますが、汚れているようには見えません。

また、まだそこにある if チェックがいくつかあります。

[編集]

上記のコードをさらに最適化できると確信しています。しかし、それは別の見方です。

于 2011-01-26T00:35:47.917 に答える