Hello, 大噶好, 小葵花媽媽課堂開課啦。。。。。。 我們日常工作中拿到的數據不可能是只有一維的平面數組, 百分之99.99 是數組裡嵌套數組再套數組的n維數組 ............................. 這種讓人想問候它xx的多維數組我們怎麼把它變成一維數組, 也就是只有一個中 ...
Hello, 大噶好, 小葵花媽媽課堂開課啦。。。。。。
我們日常工作中拿到的數據不可能是只有一維的平面數組, 百分之99.99 是數組裡嵌套數組再套數組的n維數組 .............................
這種讓人想問候它xx的多維數組我們怎麼把它變成一維數組, 也就是只有一個中括弧 的數組 呢 ?
接下來我們 一步一步來實現它 , Follow me
講降維之前, 我們先來回顧一下 數組 有哪些 方法 ?
給同學們一秒鐘時間思考。。。
請同學們 舉手回答 。。。。
OK 為了方便記憶,我們可以把數組的方法分成兩類 :
1 不改變原數組的方法
2 改變原數組的方法
先說會改變原數組的方法 :
sort() 數組的排序方法 , 可以傳一個回調函數, 不傳參數預設按照字元串的unicode碼位點排序
所以不傳參 的話 10 是 小於 2 的 。。。。先比第一位 1 < 2 ,只有第一位相等才會比第二位,
所以 10 < 2,回調函數接受兩個參數, 可以在回調函數中定義排序的規則, 執行後返回改變後的原數組
reverse() 數組逆序 執行後返回改變後的原數組
pop() 彈出數組的最後一個元素 執行後返回彈出的變數
shift() 彈出數組的第一個元素 執行後返回彈出的變數
push() 在數組的末尾加(可加多個元素) 執行後返回改變後的原數組的length
unshift() 在數組的頭部加(可加多個元素) 執行後返回改變後的原數組的length
splice(start, deleteCount, new可選) 用於刪除指定區域的元素, 並可以在刪除的區域添加新的元素
new可以是多個新元素
執行後返回被刪除的元素
copyWithin(start, end可選, stop可選) 複製 index = end 的元素 並 替換 掉 index = start 的元素 ,
stop 表示 在第幾位 停止複製( IE 11 及更早版本不支持 copyWithin() 方法),
執行後返回改變後的原數組
fill(value, start可選, end可選) 把數組的start 位 到 end 位 的元素 都用 value 替換掉 ,
只傳value,數組的所有元素都用value替換,
執行後返回改變後的原數組
不改變原數組的方法:
concat() 數組合併, 可以傳數組也可以傳參數列表 , 返回一個合併後的新數組
如果合併的數組裡面有引用值, 新數組中的引用值的地址和原來一樣,
改變其中一個,另一個也會發生改變, 所以並不能用來深拷貝。
(下一期我們會來討論一下 深淺拷貝 )
includes(value, start可選) 從start處往後查找 value 是否在數組中, 返回一個布爾值
indexOf(value, start可選) 從start 開始 往後查找 value, 返回找到的第一個值的索引,
沒找到返回-1
lastIndexOf(value, start可選) 從索引為start的元素開始往前查找,返回找到的第一個值的索引,
沒找到返回-1
join(string可選) 把數組裡的每一項用string里的符號拼接成一個字元串,
不傳參數用逗號拼接成一個字元串
find(callback) 按照callback里的篩選條件返回第一個符合條件的元素
findIndex(callback) 按照callback里的篩選條件返回第一個符合條件的元素的索引
toString() 把數組轉換成字元串 == > join() ;
slice(start可選, end可選) 從數組索引為start處開始複製到索引為(end - 1)的元素
返回一個由複製出來的元素組成的數組,
不傳參數複製整個數組,
註意:不傳參複製的數組內部如果有引用值的話,複製後引用值
指向同一個地址, 不能實現深拷貝
數組還有很多遍歷的方法我就不一一列出來了,
我們開始進入正題 。。。。。。
和 扁平化 數組有關的方法 :
1 flat(deep可選) deep降維深度 ; deep = 0 不降維
deep 等於幾 就降幾維,
不傳deep 降一維
2 flatMap(callback) callback 里可以操作數組, 只能降一維
上例子:
1 var a = [1, 2, 3, 4, 5, [2,3,4,[6,10]]]; // 3維數組 2 3 var b = a.flat(2); // 參數為 維數 減一 4 console.log(b); // b = [1, 2, 3, 4, 5, 2, 3, 4, 6, 10] 5 6 var c = a.flatMap( (value, index, array) => { //只能用於2維數組的降維 7 return value + 1; 8 }); 9 console.log(c); // c = [2, 3, 4, 5, 6, "2,3,4,6,101"]
需要註意的是:
1 flat 只能用於已知維度的數組降維
2 flatMap 如果數組內有引用值 , 引用值會先調用toString()方法轉換成字元串再進行計算
對於未知維度的數組, 我們需要 借用 reduce() 方法
reduce(callback, init可選) 俗稱累加器 callback里寫累加規則, init 為初始值
// 多維度降維使用遞歸 deepFlat = (arr) => { return arr.reduce((a, b) => { return Array.isArray(b) ? [...a, ...deepFlat(b)] : [...a, b] }, []) };
分析 給一個初始值 [] , 第一次 a = 初始值[] , b是數組的第一位 , 判斷b是否是數組,
如果是數組,遞歸繼續降維,降維的結果和a 合併
如果不是數組, 直接和a合併,
合併的結果作為下一次初始值,
第二次 a 為 上一次得到的初始值, b 為數組的第二位, 以此類推 。。。。。。。
這樣寫有個小問題, 如果第一次傳進去的不是數組的話會報錯 !
Uncaught TypeError: arr.reduce is not a function
所以如果不想加額外的判斷的話,還可以這樣寫
const flattenDeep = (arr) => { return Array.isArray(arr) ? arr.reduce((a, b) => { return [...a, ...flattenDeep(b)] }, []) : [arr] };
再分析 先判斷傳進來的實參arr是否是數組, 如果不是的話直接返回【arr】,
如果是的話 再 調用 reduce()方法 進行遞歸降維 ,
更騷的寫法
const flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce((a, b) => [...a, ...flattenDeep(b)], []) : [arr];
把 大括弧 和 return 都 去掉 , 一句話 搞定 !!!