Javascript:改进四个嵌套循环?

时间:2014-01-10 21:47:32

标签: javascript

我有一个带有嵌套数组的复杂对象数组。下面的工作是提取某些对象,但它是我写过的最丑陋的东西之一。

是否有一些优雅的javascript黑暗魔法?

function getEighthInsertionBlocks() {
    var struct = Lifestyle.Pagination.structure;
    var blocks = [];
    for (var i = 0; i<struct.length; i++) {
        var page = struct[i];
        var layers = page.children;
        for (var j=0; j<layers.length; j++) {
            var layer = layers[j];
            if (layer.className === 'EighthPageLayer' ) {
                var rows = layer.children;
                for (var k=0; k<rows.length; k++) {
                    var row = rows[k];
                    eBlocks = row.children;
                    for (var l=0; l<eBlocks.length; l++) {
                        blocks.push(eBlocks[l]);
                    }
                }
            }
        }
    }

    return blocks;
}

不是说我是代码高尔夫的忠实粉丝,但是......这太可怕了。

3 个答案:

答案 0 :(得分:3)

您可以编写一个通用迭代器,它会将代码减少为顺序块:

var iterator = function(collection, callback){
    var length = collection.length;
    var results = [];
    var result;
    for (var i = 0; i < collection.length; i++){
        result = callback(colleciton[i], i);
        if (result){
            results = results.concat(result);
        }
    }
    return results;
};

function getEighthInsertionBlocks() {
    var struct = Lifestyle.Pagination.structure;
    var layers = iterator(struct, function(page){ return page.children; });
    var rows = iterator(layers, function(layer){
        return layer.className === 'EighthPageLayer' ? layer.children : null;
    });
    return iterator(rows, function(eBlocks, index){ return eblocks[index]; });
}

答案 1 :(得分:0)

我通常倾向于使用forEach来提高可读性,但这是主观的。

function isEighthPageLayer(layer){
    return layer.className === "EighthPageLayer"
}

function getEighthInsertionBlocks(struct) {
    var blocks = [];
    struct.forEach(function(page){
        page.layers
            .filter(isEighthPageLayer)
            .forEach( function(layer) {
                layer.children.forEach(function(row){
                    row.children.forEach(function(eBlocks){
                        blocks.push(eBlocks);
                    });
                });
            });
        });
    });
    return blocks;
}

答案 2 :(得分:0)

这是一项有趣的挑战。为了避免深度嵌套,需要一个可以递归使用的泛型迭代器,但迭代中有一些特殊情况。因此,我尝试创建一个通用迭代器,您可以将选项对象传递给它以指定特殊条件。这就是我想出来的。由于我没有样本数据集,这是未经测试的,但希望您能看到这个想法:

function iterateLevel(data, options, level, output) {
    console.log("level:" + level);
    console.log(data);
    var fn = options[level] && options[level].fn;
    for (var i = 0; i < data.length; i++) {
        if (!fn || (fn(data[i]) === true)) {
            if (level === options.endLevel) {
                output.push(data[i]);
            } else {
                iterateLevel(data[i].children, options, level + 1, output);
            }
        }
    }
}

var iterateOptions = {
    "1": {
        fn: function(arg) {return arg.className === 'EighthPageLayer'}
    },
    "endLevel": 3
}
var blocks = [];
iterateLevel(Lifestyle.Pagination.structure, iterateOptions, 0, blocks);

这个想法是,options对象可以为每个级别提供一个可选的过滤函数,它会告诉你要删除多少个级别。

工作演示:http://jsfiddle.net/jfriend00/aQs6h/