GitHub地址: JavaScript30秒, 從入門到放棄之Array(七)博客地址:JavaScript30秒, 從入門到放棄之Array(七)javascript
水平有限,歡迎批評指正java
Filters out the elements of an array, that have one of the specified values.node
Use
Array.filter()
to create an array excluding(using!Array.includes()
) all given values.gitconst without = (arr, ...args) => arr.filter(v => !args.includes(v));
剔除掉數組中全部存在於所指定的元素們的項。github
使用Array.filter()
建立一個將全部提供的值排除在外(使用!Array.includes()
)的數組。數組
➜ code cat without.js const without = (arr, ...args) => arr.filter(v => !args.includes(v)); console.log(without([2, 1, 2, 3], 1, 2)); ➜ code node without.js [ 3 ]
filter
和includes
結合,把數組arr
中全部存在於指定的元素值…args
中的項排除在外,很清爽乾淨。app
Creates a new array out of the two supplied by creating each possible pair from the arrays.ide
Use
Array.reduce()
,Array.map()
andArray.concat()
to produce every possible pair from the elements of the two arrays and save them in an array.函數const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
建立一個新數組,數組元素由兩個數組的元素交叉組合而成。oop
使用Array.reduce()
,Array.map()
和Array.concat()
來建立由兩個數組元素拼接而成的全部可能對並將它們存在一個數組中的數組。
➜ code cat xProd.js const xProd = (a, b) => a.reduce((acc, val) => acc.concat(b.map(v => [val, v])), []); console.log(xProd([1, 2], ['a', 'b'])); ➜ code node xProd.js [ [ 1, 'a' ], [ 1, 'b' ], [ 2, 'a' ], [ 2, 'b' ] ]
reduce
初始值acc
是一個空數組[]
,隨着遍歷的進行acc
會concat
生成的元素組合對的數組。組合對就是由b.map(v => [val, v]
生成的。也就是reduce
遍歷一次時,數組a
的一個元素分別和數組b
的全部元素分別組成一對。
Creates an array of elements, grouped based on the position in the original arrays.
Use
Math.max.apply()
to get the longest array in the arguments. Creates an array with that length as return value and useArray.from()
with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary,undefined
is used where no value could be found.const zip = (...arrays) => { const maxLength = Math.max(...arrays.map(x => x.length)); return Array.from({ length: maxLength }).map((_, i) => { return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); }); };
建立一個數組,數組元素由指定的多個數組根據位置對應分組而成的數組構成。例如,多個數組的第一個元素組成一個新數組,第二個元素組成一個新數組,依次類推。最終把全部分類號的數組存到一個數組中。
先使用Math.max.apply()
來計算出最終成組的長度,而後使用該長度結合Array.from()
和map
去遍歷建立該數組的全部分組子數組。若是其中任意一個數組在對應位置上元素不存在(如長度爲2
的數組試圖獲取第3
個元素)則undefined
將被使用。
➜ code cat zip.js const zip = (...arrays) => { const maxLength = Math.max(...arrays.map(x => x.length)); return Array.from({ length: maxLength }).map((_, i) => Array.from({ length: arrays.length }, (_, k) => arrays[k][i])); }; console.log(zip(['a', 'b'], [1, 2], [true, false])); console.log(zip(['a'], [1, 2], [true, false])); ➜ code node zip.js [ [ 'a', 1, true ], [ 'b', 2, false ] ] [ [ 'a', 1, true ], [ undefined, 2, false ] ]
const maxLength = Math.max(...arrays.map(x => x.length));
這是最終分紅maxLength
組,好比一個數組含有100
個元素,另外一個數組含有1
個元素,最終要分紅100
組,因此須要用Math.max()
去獲取全部數組中長度最長的那個。
return Array.from({ length: maxLength }).map((_, i) => Array.from({ length: arrays.length }).map((_, k) => arrays[k][i]) );
使用Array.from
結合length
生成長度爲maxLength
的數組這沒啥說的了,重點是map
後的方法,map
的每個數組裏包含多少個元素才能夠呢?稍微想一下就知道,應該是arrays
的個數,由於每個數組都要拿一個出來組裝。因此這裏又用了一個Array.from
配上length: arrays.length
來定一個數組裏包含的元素數量。那麼這些元素由什麼組成呢?這裏仍是要配合一個(_, k) => arrays[k][i])
方法去取arrays的元素。獲取的是對應每個數組的第i
個元素。
Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.
Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using
Array.reduce()
.const zipObject = (props, values) => props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
提供一個有效的屬性標識符的數組和一個含值數組,返回一個把屬性和值拼合的對象。即有效的屬性標識符數組的第一項爲鍵,含值數組的第一項爲值,依次類推。
因爲一個對象值能夠爲undefined
而鍵不能爲undefined
,因此只有有效的屬性標識符數組能用來決定了對象的組成結構。於是使用Array.reduce()
對該數組進行相關操做。
➜ code cat zipObject.js const zipObject = (props, values) => props.reduce((acc, val, i) => ((acc[val] = values[i]), acc), {}); console.log(zipObject(['a', 'b', 'c'], [1, 2])); console.log(zipObject(['a', 'b'], [1, 2, 3])); ➜ code node zipObject.js { a: 1, b: 2, c: undefined } { a: 1, b: 2 }
(obj[prop] = values[index]), obj)
JavaScript的逗號運算符是指按照順序執行表達式,最終返回最後一個表達式的運行結果。對於這個例子來講,就是先創造一個鍵值對,最後返回該對象。換通常的寫法就是以下:
obj[prop] = values[index]; return obj;
這點弄通了就好理解了。
實際上就是以props
數組爲基準,對其運用reduce
方法去遍歷數組,初始值obj
是一個空對象{}
,遍歷過程以props
數組的值prop
爲鍵,props
數組當前索引index
爲索引去取values
數組的項爲值組裝成對象並返回。
因爲對象的鍵不能爲undefined
,所以,若是數組props
的長度比數組values
小,那麼values
多出來的那些項就無論了。若是相反,那麼該對象相應鍵的值爲undefined
。
Creates an array of elements, grouped based on the position in the original arrays and using function as the last value to specify how grouped values should be combined.
Check if the last argument provided in a function. Use
Math.max()
to get the longest array in the arguments. Creates an array with that length as return value and useArray.from()
with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary,undefined
is used where no value could be found. The function is invoked with the elements of each group(...group)
.const zipWith = (...arrays) => { const length = arrays.length; let fn = length > 1 ? arrays[length - 1] : undefined; fn = typeof fn == 'function' ? (arrays.pop(), fn) : undefined; const maxLength = Math.max(...arrays.map(x => x.length)); const result = Array.from({ length: maxLength }).map((_, i) => { return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); }); return fn ? result.map(arr => fn(...arr)) : result; };
建立一個數組,數組元素由指定的多個數組根據位置對應分組而成的數組構成,而後分組後的數組元素應用指定方法進行結合。
➜ code cat zipWith.js const zipWith = (...arrays) => { const length = arrays.length; let fn = length > 1 ? arrays[length - 1] : undefined; fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined; const maxLength = Math.max(...arrays.map(x => x.length)); const result = Array.from({length: maxLength}).map((_, i) => {return Array.from({length: arrays.length}, (_, k) => arrays[k][i]);}); return fn ? result.map(arr => fn(...arr)) : result; }; console.log(zipWith([1, 2], [10, 20], [100, 200], (a, b, c) => a + b + c)); console.log(zipWith( [1, 2, 3], [10, 20], [100, 200], (a, b, c) => (a != null ? a : 'a') + (b != null ? b : 'b') + (c != null ? c : 'c') )); ➜ code node zipWith.js [ 111, 222 ] [ 111, 222, '3bc' ]
const length = arrays.length; let fn = length > 1 ? arrays[length - 1] : undefined; fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined;
首先這裏把參數長度arrays.length
存到length
裏,而後根據參數長度length
判斷參數裏是否指定了某個方法。若是length
小於等於1
,則沒有傳入指定方法,於是fn = undefined
;不然,認爲參數的最後一個arrays[length - 1]
傳入了方法。
接下來還得判斷fn
是否是一個function
,若是是,arrays.pop()
把方法剔除,只留數組,而後返回fn
賦值給fn
;不然把undefined
賦值給fn
。
其實我以爲這裏和前面的寫重複了,我以爲fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined
改爲下面更好:
if (typeof fn === 'function') { arrays.pop(); }
這樣就避免了fn
的重複賦值了。由於fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined
這一行的做用就是爲了把方法pop
出去而已,不必再從新賦值。
const maxLength = Math.max(...arrays.map(x => x.length));
這一行計算出最終返回數組的長度,這點易證,不展開。
const result = Array.from({ length: maxLength }).map((_, i) => { return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); });
這裏其實和前面的zip
方法是同樣的,到如今爲止返回的result
是和zip
的結果是同樣的。
return fn ? result.map(arr => fn(...arr)) : result;
而後判斷fn
是否是非undefined
,若是是不用處理直接返回result
,不然對result
數組全部元素調用fn
方法並返回結果。須要注意的是參數…arr
是須要展開的,參數不是單個的數組元素,而是數組的全部元素。
Returns
true
if all elements in a collection are truthy,false
otherwise.Use
Array.every(Boolean)
to test if all elements in the collection are truthy.const all = arr => arr.every(Boolean);
若是數組全部元素爲真,返回true
,不然返回false
。
使用 Array.every(Boolean)
來檢測數組全部元素是否都爲真。
➜ code cat all.js const all = arr => arr.every(Boolean); console.log(all([1, 2, 3])); ➜ code node all.js true
這其實就是Array.every()
函數能作的事情。參數爲Boolean
就是判斷是否是數組全部元素布爾爲都爲真。
Returns
true
if the provided predicate function returnstrue
for all elements in a collection,false
otherwise.Use
Array.every()
to test if all elements in the collection returntrue
based onfn
.const allBy = (arr, fn) => arr.every(fn);
若是數組全部元素應用了指定的斷言方法都爲真,那麼返回true
,不然返回false
。
使用Array.every()
結合fn
來檢測數組全部元素調用fn
後布爾值是否都爲真。
➜ code cat allBy.js const allBy = (arr, fn) => arr.every(fn); console.log(allBy([4, 2, 3], x => x > 1)); ➜ code node allBy.js true
比all
多了一個fn
方法而已,只須要把every
的參數換成fn
就行,這沒啥可說的。
Returns
true
if at least one element in a collection is truthy,false
otherwise.Use
Array.some(Boolean)
to test if any elements in the collection are truthy.const any = arr => arr.some(Boolean);
若是一個數組中至少有一個元素布爾值爲真,返回true
,不然返回false
。
使用Array.some(Boolean)
來檢測數組中是否有一個元素布爾值爲真。
➜ code cat any.js const any = arr => arr.some(Boolean); console.log(any([0, 0, 1, 0])); ➜ code node any.js true
這就是Array.some()
能夠作的事情,沒啥可說。
Returns
true
if the provided predicate function returnstrue
for at least one element in a collection,false
otherwise.Use
Array.some()
to test if any elements in the collection returntrue
based onfn
.const anyBy = (arr, fn) => arr.some(fn);
若是對一個數組的元素運用指定的斷言方法後至少有一個結果布爾值爲真,返回true
,不然返回false
。
使用Array.some()
結合fn
檢測一個數組中調用指定斷言方法後至少有一個結果布爾值爲真。
➜ code cat anyBy.js const anyBy = (arr, fn) => arr.some(fn); console.log(anyBy([0, 1, 2, 0], x => x >= 2)); ➜ code node anyBy.js true
比any
多了一個fn
方法而已,只須要把some
的參數換成fn
就行,這沒啥可說的。
Splits values into two groups. If an element in
filter
is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group.Use
Array.reduce()
andArray.push()
to add elements to groups, based onfilter
.const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
把一個數組分裂成兩組。若是一個元素在filter
中對應值是truthy
,那麼相應位置的被分裂元素歸屬於第一個組,不然歸屬於第二個組。
使用Array.reduce()
和Array.push()
在filter
的基礎上把待分裂的元素添加到相應的組中。
➜ code cat bifurcate.js const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); console.log(bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true])); ➜ code node bifurcate.js [ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]
reduce
初始值acc
是一個含有兩個空數組的二維數組[[], []]
,遍歷過程當中去判斷對應索引filter
的值filter[i]
是否爲truthy
,若真,則把當前索引對應元素val
加到acc[0]
中;不然加到acc[1]
中。遍歷結束,分組完成。
Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group.
Use
Array.reduce()
andArray.push()
to add elements to groups, based on the value returned byfn
for each element.const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
根據提供的斷言方法將一個數組分裂成兩組。若是斷言結果爲truthy
,該元素將被分配到第一組,不然分配在第二組。
使用Array.reduce()
和Array.push()
在斷言方法fn
的基礎上將待分裂的元素添加到相應的組中。
➜ code cat bifurcateBy.js const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); console.log(bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b')); ➜ code node bifurcateBy.js [ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]
跟bifurcate
相比不一樣的地方是:
(acc[fn(val, i) ? 0 : 1].push(val), acc)
這裏是對數組的元素val
調用指定方法,而bifurcate
是對應位置filter[i]
的直接結果。其他都是同樣的。這也很好理解了。