從一個地圖資料結構延伸出對JS陣列操作的一些思考

Emine發表於2019-02-27

今天上午的時候正在興致勃勃的寫著bug,突然微信 “tututu~”的響了起來,點開一看,是一位前端新朋友給我發來的這樣一個問題

從一個地圖資料結構延伸出對JS陣列操作的一些思考

當時內心就是“這都什麼年代了,還問這種陣列問題,問我問題的標準線起碼怎麼說也要是三維空間中的二維圖形的幾何變換啊三大庫的底層的原始碼的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 返回那條滿足我的資料!

測試一哈~

從一個地圖資料結構延伸出對JS陣列操作的一些思考

頭皮發麻!盆友們,頭皮發麻感受到了嗎? 查 ‘路南區’,把河北下邊的‘石家莊’、‘唐山’ 都給我了,可是我就想要 ‘河北’->‘唐山’->‘路南區’

改一下唄,‘還能離咋滴’...

於是成了:

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
    }
}複製程式碼

測試:

從一個地圖資料結構延伸出對JS陣列操作的一些思考

bingo~ 成功選好牛肉麵!


PS: 其實寫完後感覺,可以做的更通用一點,遞迴查詢...有空試一試~~


相關文章