Javascript:改进四个嵌套循环?

Javascript:改进四个嵌套循环?,javascript,Javascript,我有一个包含嵌套数组的复杂对象数组。下面的工作是提取某些对象,但这是我写过的最丑陋的东西之一 是否有一些javascript黑魔法可以优雅地做到这一点 function getEighthInsertionBlocks() { var struct = Lifestyle.Pagination.structure; var blocks = []; for (var i = 0; i<struct.length; i++) { var page =

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

是否有一些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;
}
函数GetEighthineSertionBlocks(){ var struct=lively.Pagination.structure; var块=[];
对于(var i=0;i我通常倾向于使用
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;
}

您可以编写一个通用迭代器,该迭代器将代码缩减为连续块:

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]; });
}
var迭代器=函数(集合、回调){
var length=collection.length;
var结果=[];
var结果;
对于(变量i=0;i
这是一个有趣的挑战。为了避免深度嵌套,您需要一个可以递归使用的泛型迭代器,但在您的迭代中有一些特殊情况。因此,我尝试创建一个泛型迭代器,您可以将options对象传递给它,以指定特殊条件。下面是我的想法。因为我不知道有一个样本数据集,这是未经测试的,但希望您看到这个想法:

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);
function iterateLevel(数据、选项、级别、输出){
控制台日志(“级别:+级别);
控制台日志(数据);
var fn=期权[级别]&期权[级别].fn;
对于(变量i=0;i
其思想是,options对象可以为每个级别提供一个可选的过滤函数,它告诉您要降低多少级别


工作演示:

你完全是标准的。只是一个想法,使用一个Frach循环将每个循环都变成一个方法可能更容易管理。需要深入迭代的深层结构;。不管您用什么方式编写,它都会慢一些,尽管您可以将所有变量声明移到函数的顶部。您可以使用
map
filter
来摆脱难看的循环和中间变量。但是速度可能会慢一些。当然,我们的目标是从filter中提取一些函数,例如每一个。我认为最好的候选函数是采用层参数的函数。我提出一个警告。@farvilian您可以将传递给
forEach
的函数提取到变量中,这将是一个非常优雅的解决方案(太好了!:)比我的解决方案更好!为了实现这一点,我们需要将结果串联起来,而不是推送它们。否则,我们将非常有效ely实现
Array.prototype.map
@Peter我不确定我是否遵循了你的逻辑。这在没有concat的情况下可以工作。另外,
Array.prototype.map
没有IE8支持(如果需要的话)@Stephen我的意思是,这本质上是一个映射,而不是一个concat。它现在的工作方式是将
设置为一个数组。这意味着在处理行时,我们只迭代
层。长度
项,并接收子项数组作为项,因此不会迭代子项。