Итерация через вложенные объекты JavaScript - грязные? - PullRequest
0 голосов
/ 26 января 2011

У меня есть немного 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 , которое сопоставляется со всеми доступными цветами для размера.Каждое комбо также имеет свойство amountOnHand , которое сообщает количество, доступное для этого конкретного комбо.(возвращаемая структура JSON не может быть изменена)

Код выполняет цикл по каждому размеру, а затем по комбо каждого размера.Затем он проверяет, можно ли скомбинировать размер и цвет (с помощью другого метода).Если любой комбо может быть переназначен, мы можем остановиться, потому что количество по умолчанию определено в другом месте.Если комбо не подлежит сортировке, max_default_quantity является наибольшим значением, которое мы находим (с максимальным значением settings.limitedStockThreshold).

Мне действительно не нравятся вложенные циклы for и моя обработка математики и значения по умолчаниюзначения кажутся слишком сложными.

Кроме того, вся эта функция обернута в гораздо больший объект jQuery, если это помогает его очистить.

Ответы [ 2 ]

0 голосов
/ 26 января 2011

Рассматривали ли вы использовать карту-уменьшить?См. live пример функционального подхода.

В этом конкретном примере используется 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);
}

Что касается объяснения:

Мы берем набор инвентаризированный размер и удаляем все, которые не содержат комбо.Затем мы сопоставляем каждый размер с максимальным количеством его цвета.Мы делаем это, сопоставляя каждую комбинацию либо с ее количеством, либо с максимальным количеством, если оно может быть перенесено.Затем мы берем максимум из этого набора.

Наконец, мы берем максимум из набора maxQuantities на размер.

Мы по-прежнему эффективно выполняем двойной цикл for, так как мы берем два .maxна съемочной площадке, но выглядит не так грязно.

Есть также несколько проверок if, которые были у вас на месте, которые все еще там.

[Редактировать]

Я уверен, что приведенный выше код можно оптимизировать намного больше.но это другой взгляд на это.

0 голосов
/ 26 января 2011

К сожалению, JavaScript не имеет особых возможностей для элегантной обработки коллекций, если вам необходимо поддерживать старые браузеры, поэтому без помощи дополнительных библиотек можно использовать вложенный цикл, подобный тому, который вы написали.,Вы могли бы рассмотреть возможность предварительно вычислять значения на стороне сервера, возможно, кэшировать и включать их в JSON, чтобы избежать необходимости повторять одни и те же вычисления снова и снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...