从一个地图数据结构延伸出对JS数组操作的一些思考

本文介绍了一种使用ES6语法在复杂嵌套数组中查找特定元素的方法。通过find、some等函数,实现对深层数据结构的有效遍历,最终精确定位目标元素。

今天上午的时候正在兴致勃勃的写着bug,突然微信 “tututu~”的响了起来,点开一看,是一位前端新朋友给我发来的这样一个问题

当时内心就是“这都什么年代了,还问这种数组问题,问我问题的标准线起码怎么说也要是三维空间中的二维图形的几何变换啊三大库的底层的源码的C是如何运行的啊之类的问题吧”,然后嘴上说着“小case”,手上回复着“马上就给你解决”。

他的数据结构是介样婶儿的:

var cityStr =[  
{ "name": "北京", "city": [{ "name": "北京", "area": ["东城区", "西城区"] }] },  
{ "name": "天津", "city": [{ "name": "天津", "area": ["和平区", "河东区"] }] },  
{ "name": "河北", "city": [{ "name": "石家庄", "area": ["长安区", "桥东区"] },                           
                          { "name": "唐山", "area": ["路南区", "路北区"] }
                         ]
}
]复制代码

他的要求是:输入 “路南区”,能找到 它是在 “河北” -> “唐山” -> “路南区”。

其实看到这个要求,咱们肯定是想 “管他什么什么的,哥们儿都是一把梭,遍历遍历!”

当然哥们我也是一把梭走天下,不就是遍历嘛,嘴角疯狂上扬动,

for(let i = 0; i < cityStr.length; i++) {    
    for(let j = 0; j < cityStr['city'].length; j++) {        
        for(let k = 0; k < cityStr['city']['area'].length; k++) {           
             // 写到这里,嘴角的微笑逐渐凝固..        
        }    
    }
}复制代码

卧槽,我已经晕了,梭不动了,层级套太多了,而且再来一层数组结构?那只能直接选择狗带了,不行,换一个,突然灵光一现,“不如来点更ES6的写法”,这是来自灵光界的一声暗呼。

说干就干,于是赶紧 command+a command+x ,空空的编辑器顿时就让我的呼吸也变得轻松了起来,写es6的诀窍就在于 “管他能不能写出来,先写一个function”,是的,写上 function filterFc() {} 的感觉像极了小学不会做的数学题但是写上了 “答:” 一样,舒畅~

function filterFc(address: string):any {
    return (这里要抛出address对应的父地点)
}复制代码

写到这里,心中顿时感觉 “成了!”抛出地点嘛,接下来,就是怎么抛地点出来。

怎么抛?又是一场遍历?不过既然要es6一点,那就不会再 for 了,es6的遍历多了,forEach, map, some, filter, find ... 哥如同后宫选妃侍寝一般,对数组api挑过来挑过去,不过逐渐意识到,好像能陪我走下去的它,并不是看上去那么多。

forEach?不行,它只能使用try...catch...进行中断,还不输出东西,宛如我要紫薇她确实容嬷嬷。

map?好像可以,抛出一个数组 [省,市,区] ,可以嘛,但是~,map也是无法中断的操作,那么找到了,还进行遍历好像是很没有必要的操作啊,就像吃了两碗牛肉面饱了了,你再喂我吃牛肉面?

filter?返回一个内部所有为true值的数据组成的数组,好像还是要面对吃牛肉面的问题...

find?返回第一个符合条件的牛肉面,进入视野 ✔️

some?返回布尔值,又是进入了我视野的牛肉面 ✔️

于是我就抠破了脑袋写下了:

var cityStr =    [        { "name": "北京", "city": [{ "name": "北京", "area": ["东城区", "西城区"] }] },        { "name": "天津", "city": [{ "name": "天津", "area": ["和平区", "河东区"] }] },        {            "name": "河北", "city": [{ "name": "石家庄", "area": ["长安区", "桥东区"] },                                    { "name": "唐山", "area": ["路南区", "路北区"] },                                    ]        }    ]
function filterFc(address: string):any {
    return cityStr.find((value:any, key: number, array: any[]): boolean => {
        return value['city'].some((v: any, k: number, arr: any[]): boolean => {
            return v['area'].some((ad: string, adKey: number): boolean => {
                return ad === address
            })
        })
    })
}复制代码

来分析一下为啥要这么写(简短分析,毕竟头顶凉嗖嗖的)

v['area'].some((ad: string, adKey: number): boolean => {
                return ad === address
})复制代码

通过 ‘area’ 字段比对输入区的名字在不在本 ‘area’ 里边,返回一个Boolean值,

value['city'].some((v: any, k: number, arr: any[]): boolean => {
            return v['area'].some((ad: string, adKey: number): boolean => {
                return ad === address
            })
})复制代码

抓住地区比对抛出的Boolean值,继续朝上抛出,这是同一步骤,最后

cityStr.find((value:any, key: number, array: any[]): boolean => {
        return value['city'].some((v: any, k: number, arr: any[]): boolean => {
            return v['area'].some((ad: string, adKey: number): boolean => {
                return ad === address
            })
        })
})复制代码

find函数能够用于找出第一个符合条件的数组成员,也就是说,只要你给我返回true,那么我就给你返回这条返回true的数据,这个API真是“像极了爱情”,正是我所需要的!函数 filterFc 返回那条满足我的数据!

测试一哈~


头皮发麻!盆友们,头皮发麻感受到了吗? 查 ‘路南区’,把河北下边的‘石家庄’、‘唐山’ 都给我了,可是我就想要 ‘河北’->‘唐山’->‘路南区’

改一下呗,‘还能离咋滴’...

于是成了:

var cityStr =    [        { "name": "北京", "city": [{ "name": "北京", "area": ["东城区", "西城区"] }] },        { "name": "天津", "city": [{ "name": "天津", "area": ["和平区", "河东区"] }] },        {            "name": "河北", "city": [{ "name": "石家庄", "area": ["长安区", "桥东区"] },            { "name": "唐山", "area": ["路南区", "路北区"] },            ]        }    ]
function filterFc(address: string):any {
    let ad = {},
        res = []

    let s = cityStr.some((value:any, key: number, array: any[]) => {
        if(
          value['city'].some((v: any, k: number, arr: any[]) => {                if (v['area'].includes(address)) {                    ad = arr[k]                    return true                }                            })        ) {
          res = [array[key]['name'], ad]
          return true
        }
    })
    
    if(s) {
        return res
    }
}复制代码

测试:


bingo~ 成功选好牛肉面!


PS: 其实写完后感觉,可以做的更通用一点,递归查找...有空试一试~~


转载于:https://juejin.im/post/5c7624aa51882562ec592a64

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值