原文連接: JavaScript30秒, 從入門到放棄之Array(三)水平有限,歡迎批評指正javascript
Flattens an array up to the specified depth.java
Use recursion, decrementing
depth
by 1 for each level of depth. UseArray.reduce()
andArray.concat()
to merge elements or arrays. Base case, fordepth
equal to1
stops recursion. Omit the second element,depth
to flatten only to a depth of1
(single flatten).nodeconst flattenDepth = (arr, depth = 1) => depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []) : arr.reduce((a, v) => a.concat(v), []);
把一個數組按指定深度進行攤平。git
使用遞歸方法,對於任意級別的深度depth
,每次遞歸depth
減1
。使用Array.reduce()
和Array.concat()
來合併元素們或者數組們。直到depth
遞減到1
時中止遞歸。省略第二個參數depth
時,按深度depth
爲1
計(即單層攤平)。github
➜ code cat flattenDepth.js const flattenDepth = (arr, depth = 1) => depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []) : arr.reduce((a, v) => a.concat(v), []); console.log(flattenDepth([1, [2], 3, 4])); console.log(flattenDepth([1, [2, [5]], 3, 4])); ➜ code node flattenDepth.js [ 1, 2, 3, 4 ] [ 1, 2, [ 5 ], 3, 4 ]
根據depth
來決定處理流程,若depth
存在且不等於1
則進行遞歸:數組
arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
用了reduce()
去處理循環時的每個值,同時用concat
把全部遞歸結果拼接成新數組返回。循環過程當中,對值進行數組判斷Array.isArray(v)
,是數組,flattenDepth(v, depth - 1)
深度減1
繼續遞歸直到depth
爲1
爲止;不是數組,直接返回該值v
,供concat
拼接。微信
不然,直接循環去拼接該值返回:閉包
arr.reduce((a, v) => a.concat(v), []);
Groups the elements of an array based on the given function.app
Use
Array.map()
to map the values of an array to a function or property name. UseArray.reduce()
to create an object, where the keys are produced from the mapped results.ideconst groupBy = (arr, func) => arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {});
按照指定的方法對數組元素進行分組歸類。
使用Array.map()
對全部數組元素調用指定方法或者調用返回該元素的屬性值的方法。使用Array.reduce()
建立一個對象,對象的鍵是map
生成的結果,值是符合該鍵的全部數組元素組成的數組。
➜ code cat groupBy.js const groupBy = (arr, func) => arr.map(typeof func === 'function' ? func : val => val[func]). reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {}); console.log(groupBy([6.1, 4.2, 6.3], Math.floor)); console.log(groupBy(['one', 'two', 'three'], 'length')); ➜ code node groupBy.js { '4': [ 4.2 ], '6': [ 6.1, 6.3 ] } { '3': [ 'one', 'two' ], '5': [ 'three' ] }
代碼拆分:
arr.map(typeof func === 'function' ? func : val => val[func])
對第二個參數func
的類型進行判斷,如果function,則對數組arr
全部元素調用該方法,返回一個新的數組。如:
const arr = [1, 2, 3, 4]; arr.map(x => x * x); // [1, 4, 9, 16]
不然,調用返回該元素對應func
屬性值方法:
const arr = ['one', 'two', 'three']; const func = 'length'; arr.map(val => val[func]); // [3, 3, 5]
reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {})
acc
是reduce
過程當中累積的結果,val
是reduce
的主體(即前邊map
的結果數組)每次循環時數組元素的值,i
則是主體數組循環時對應的索引。
第一個循環時acc
的初始值是一個空對象{}
,循環過程當中先判斷是否已經有以val
爲鍵的值,若是尚未,建立一個空數組把此時對應索引i
的數組值arr[i]
拼接,做爲以val
爲鍵的值;不然,直接拼接arr[i]
。便是acc[val] = (acc[val] || []).concat(arr[i])
作的事。每次循環都返回acc
對象,直到循環結束,生成分類結果。
連起來就是說先對數組arr
元素進行map
,map
結果做爲鍵,全部map
結果相同的數組元素arr[i]
歸到一個數組中做爲該鍵的值。最終返回一個分好類的對象。
Returns the head of a list.
Use
arr[0]
to return the first element of the passed array.const head = arr => arr[0];
返回數組第一個元素。
使用arr[0]
返回指定數組arr
的第一個元素。
➜ code cat head.js const head = arr => arr[0]; console.log(head([1, 2, 3])); ➜ code node head.js 1
Returns all the elements of an array except the last one.
Use
arr.slice(0,-1)
to return all but the last element of the array.const initial = arr => arr.slice(0, -1);
返回除數組最後一個元素外的全部元素組成的新數組。
使用arr.slice(0, -1)
返回數組除最後一個元素外的全部元素。
➜ code cat initial.js const initial = arr => arr.slice(0, -1); console.log(initial([1, 2, 3])); ➜ code node initial.js [ 1, 2 ]
arr.slice(0, -1)
立竿見影,實在沒啥可說。
Initializes a 2D array of given width and height and value.
Use
Array.map()
to generate h rows where each is a new array of size w initialize with value. If the value is not provided, default tonull
.const initialize2DArray = (w, h, val = null) => Array(h) .fill() .map(() => Array(w).fill(val));
初始化一個給定寬(列)、高(行)和值的二維數組。
使用Array.map()
來生成一個h
行的數組。每一行含有w
個值爲指定值的元素。若是未指定任何值,數組的默認值是null
。
➜ code cat initialize2DArray.js const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val)); console.log(initialize2DArray(2, 2, 0)); ➜ code node initialize2DArray.js [ [ 0, 0 ], [ 0, 0 ] ]
Array(h).fill()
先建立一個含有h
個元素的數組並將它們所有默認填充爲undefined
。而後在生成的數組基礎上,每一個數組元素調用一個生成w
個元素的數組且每一個位置的值都填充爲val
方法。這樣就生成了h
行w
列的二維數組。
Initializes an array containing the numbers in the specified range where
start
andend
are inclusive.Use
Array((end + 1) - start)
to create an array of the desired length,Array.map()
to fill with the desired values in a range. You can omitstart
to use a default value of0
.const initializeArrayWithRange = (end, start = 0) => Array.from({ length: end + 1 - start }).map((v, i) => i + start);
初始化一個包含start
和end
的有序數值的數組。
使用Array((end + 1) - start)
生成所指望的數組,使用Array.map()
去填充所指望的有序的數值。若省略start
,則start
默認值爲0
。
➜ code cat initializeArrayWithRange.js const initializeArrayWithRange = (end, start = 0) => Array.from({ length: end + 1 - start }).map((v, i) => i + start); console.log(initializeArrayWithRange(5)); console.log(initializeArrayWithRange(7, 3)); ➜ code node initializeArrayWithRange.js [ 0, 1, 2, 3, 4, 5 ] [ 3, 4, 5, 6, 7 ]
{length: end + 1 - start}
生成的數組長度是end + 1 -start
,而(v, i) => i + start
按i
從0
開始循環,直到length - 1
爲止。而i + start
則表示元素值從0 + start
開始遞增。
Initializes and fills an array with the specified values.
Use
Array(n)
to create an array of the desired length,fill(v)
to fill it with the desired values. You can omitvalue
to use a default value of0
.const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
初始化一個數組並所有填充指定值。
Array(n)
生成指望長度的數組,fill(v)
填充指望的值。若省略第二個參數value
,則value
默認爲0
。
➜ code cat initializeArrayWithValues.js const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value); console.log(initializeArrayWithValues(5, 2)); ➜ code node initializeArrayWithValues.js [ 2, 2, 2, 2, 2 ]
Array(n).fill(value)
一步到位,沒啥可說的了。
Returns a list of elements that exist in both arrays.
Create a
Set
fromb
, then useArray.filter()
ona
to only keep values contained inb
.const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
返回兩個數組的交集。
首先建立一個b
數組的集合,而後使用Array.filter()
去篩選出a
數組中存在於b
數組中的元素。
➜ code cat intersection.js const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); }; console.log(intersection([1, 2, 3], [4, 3, 2])); ➜ code node intersection.js [ 2, 3 ]
const s = new Set(b)
先用集合把b
數組去重,而後a.filter(x => s.has(x))
過濾數組a
,返回全部存在於s
集合中元素組成的數組。
Returns the last element in an array.
Use
arr.length - 1
to compute the index of the last element of the given array and returning it.const last = arr => arr[arr.length - 1];
返回數組的最後一個元素。
用arr.length - 1
去計算一個數組最後一個元素的索引值並返回其對應的數組元素。
➜ code cat last.js const last = arr => arr[arr.length - 1]; console.log(last([1, 2, 3])); ➜ code node last.js 3
Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.
Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new
Array
to store the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) ))();
把一個數組調用指定的方法後生成一個對象,對象的鍵是數組的元素值,對象的值是該元素值調用指定方法後生成的結果。
使用內部匿名函數定義一個不污染全局變量的命名空間並用閉包存儲返回值。使用一個新的數組來存儲一個包含arr
數組和arr
數組去map
指定方法後生成的數組。並在前面數組的基礎上藉助,
運算符去一步步的生成所須要的對象。避免了上下文環境context
來回轉換(得益於閉包和運算順序)。 (這塊不是太懂)
➜ code cat mapObject.js const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) ))(); const squareIt = arr => mapObject(arr, a => a * a); console.log(squareIt([1, 2, 3])); ➜ code node mapObject.js { '1': 1, '2': 4, '3': 9 }
逗號運算符會返回最後一個運算表達式運算的結果,如:
const i = 0 i + 1, i // i = 1
即先進行i + 1
運算,爲1
,而後返回i
即1
。
以上代碼含有兩個逗號運算表達式:
((acc[val] = a[1][ind]), acc)
即先作(acc[val] = a[1][ind])
這個運算,而後返回acc
。
第二個是:
(a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
即在a = [arr, arr.map(fn)]
定義了a
的基礎上去運用後面的reduce
方法,最後返回reduce
方法的結果。
能夠看出,先定義了一個長度爲2的數組a
,索引0
對應值爲數組arr
,索引1
對應值爲數組arr
調用fn
後的map
結果數組。而後去reduce
生成以arr
元素值爲對象鍵(即val
,也即a[0]
數組遍歷過程當中的元素值),以對應該元素值調用fn
後的結果值(即a[1][ind]
)爲對象值的對象。這個對象就是最終想要的結果。
一個時間處理庫:now.js,以爲還行的話,點個贊再走唄。。。