banner

关于多维数组取数据的循环浅谈

这个问题的起源,来自我在Coding的冒泡中,看到某位泡友的根据返回地区id查询对应的名称;

看了写法以后,不禁想起我这些年做的类似栗子。

突然想到了一些可取之处,在这里总结一些开发经验。

首先,我先预设一个虚构的多维数组结构

var data = [
    {
        "id": 1,
        "name": "A",
        "list": [
            {
                "id": 1,
                "name": "AA",
                "list": [
                    {
                        "id": 1,
                        "name": "AAA"
                    },
                    {
                        "id": 2,
                        "name": "AAB"
                    }
                ]
            },
            {
                "id": 2,
                "name": "AB",
                "list": [
                    {
                        "id": 1,
                        "name": "ABA"
                    },
                    {
                        "id": 2,
                        "name": "ABB"
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "name": "B",
        "list": [
            {
                "id": 1,
                "name": "BA",
                "list": [
                    {
                        "id": 1,
                        "name": "BAA"
                    },
                    {
                        "id": 2,
                        "name": "BAB"
                    }
                ]
            },
            {
                "id": 2,
                "name": "BB",
                "list": [
                    {
                        "id": 1,
                        "name": "BBA"
                    },
                    {
                        "id": 2,
                        "name": "BBB"
                    }
                ]
            }
        ]
    }
]

考虑到篇幅的问题,做了2*2*2的多维数组;

现已知id(1,1,2) 求对应的Name组成值;


实现方法1,最原始,最消耗资源的写法:

var ids = [1, 1, 2]
var names = []
for (var i = 0; i < data.length; i++) {
    if (data[i].id == ids[0]) {
        names.push(data[i].name)
        for (var j = 0; j < data[i].list.length; j++) {
            if (data[i].list[j].id == ids[1]) {
                names.push(data[i].list[j].name)
                for (var k = 0; k < data[i].list[j].list.length; k++) {
                    if (data[i].list[j].list[k].id == ids[1]) {
                        names.push(data[i].list[j].list[k].name)
                    }
                }
            }
        }
    }
}
console.log(names.join(",")) // A,AA,AAB

这种写法,算是最粗暴的写法了,直接嵌套三个for循环,然后得到数据;

在我们初学程序代码的时候,这种写法估计写过不少,后来成熟一些后,对其进行改进


实现方法2,简单优化的方法1:

// 简单优化
var ids = [1, 1, 2]
var names = []
for (var i = 0, n = data.length; i < n; i++) {
    if (data[i].id == ids[0]) {
        names.push(data[i].name)
        for (var j = 0, z = data[i].list.length; j < z; j++) {
            if (data[i].list[j].id == ids[1]) {
                names.push(data[i].list[j].name)
                for (var k = 0, x = data[i].list[j].list.length; k < x; k++) {
                    if (data[i].list[j].list[k].id == ids[1]) {
                        names.push(data[i].list[j].list[k].name)
                        break
                    }
                }
                break
            }
        }
        break
    }
}
console.log(names.join(",")) // A,AA,AAB

现在单独声明长度,添加了break阻止不必要继续循环,算是有所成长,但依旧很粗暴


实现方法3,ES3环境,相对靠谱的写法

// ES3环境下,我目前最好的优化
var ids = [1, 1, 2]
var names = [], 
    list1 = [],
    list2 = []
for (var i = 0, n = data.length; i < n; i++) {
    if (data[i].id == ids[0]) {
        names.push(data[i].name)
        list1 = data[i].list
        break
    }
}
for (var i = 0, n = list1.length; i < n; i++) {
    if (list1[i].id == ids[1]) {
        names.push(list1[i].name)
        list2 = list1[i].list
        break
    }
}
for (var i = 0, n = list2.length; i < n; i++) {
    if (list2[i].id == ids[2]) {
        names.push(list2[i].name)
        break
    }
}
console.log(names.join(",")) // A,AA,AAB

虽然还是三个for循环,但其中改进的地方,就不是一点点了。

针对这三种写法,我们做一个计算题,大概就知道其中的优势了;

方法1,循环次数为 2*2*2;属于一定会执行这么多次的写法;

方法2,循环次数最小为1+1+1,最大为2*2*2,这个取决于id的次数计算,只是让你感觉会比方法1的压力小很多;

方法3,循环次数最小为1+1+1,最大为2+2+2,同样是取决于id的次数计算,加法远比乘法轻松很多;假设,我们这栗子是10*10*10的多维数组,30与1000之间差距,是否就很明显了?


当然,我写这些东西,并不是要否定for嵌套循环的左右,只是大家需要考虑到善用循环嵌套,才能写出最漂亮的代码。


嗯,放一个ES6版的写法

// ES6,就简单多了
var ids = [1, 1, 2]
var names = []
let obj_1 = data.find(item => { return item.id == ids[0] })
let obj_2 = obj_1.list.find(item => { return item.id == ids[1] })
let obj_3 = obj_2.list.find(item => { return item.id == ids[2] })
names.push(obj_1.name)
names.push(obj_2.name)
names.push(obj_3.name)
console.log(names.join(",")) // A,AA,AAB

这个算是比较少和漂亮的代码,如果数组数据更为庞大,有时候需要更好的递归写法,这个就是我暂时没法演示的内容了。

关于array.find,需要了解的朋友,可以前往MDN查询

阅读: 6211
在同意共创许可协议(CC BY-NC-SA-4.0)的前提下,您可以转载本文。
橙色阳光
https://oss.so/article/97

相关阅读

留言评论

暂无留言