通过嵌套的JavaScript对象进行迭代 - 脏?

时间:2011-01-26 00:02:26

标签: javascript jquery javascript-objects

我有一些我在紧要关头写的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对象中,如果这有助于清理它。

2 个答案:

答案 0 :(得分:0)

不幸的是,如果你不得不支持旧浏览器,那么JavaScript在优雅的集合处理能力方面没有太大的作用,所以没有其他库的帮助,你编写的嵌套循环就是要走的路。 。您可以考虑将值预先计算在服务器端,也就是缓存,并将其包含在JSON中,以避免不得不一次又一次地运行相同的计算。

答案 1 :(得分:0)

您是否考虑过使用map-reduce?请参阅功能方法的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);
}

至于解释:

我们设置inventory.sizes并删除任何不包含组合的内容。然后,我们将每个尺寸映射到它的最大颜色数量。我们这样做将每个组合映射到其数量或最大数量(如果可回溯)。然后我们采取最大值。

最后,我们采用每个大小最大的maxQuantities集。

我们仍然有效地进行双循环,因为我们在集合上取两个.max但它看起来并不脏。

还有一些if check that that that that that。

[编辑]

我很确定上面的代码可以进行更多优化。但这是另一种看待它的方式。