原文地址: JavaScript30秒, 從入門到放棄之Array(六)博客地址:JavaScript30秒, 從入門到放棄之Array(六)javascript
水平有限,歡迎批評指正java
Returns all elements in an array except for the first one.node
Return
Array.slice(1)
if the array'slength
is more than1
, otherwise, return the whole array.gitconst tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
返回除了數組第一個元素之外的全部元素。github
若是數組長度大於1
,則用Array.slice(1)
返回;不然返回整個數組。數組
➜ code cat tail.js const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); console.log(tail([1, 2, 3])); console.log(tail([1])); ➜ code node tail.js [ 2, 3 ] [ 1 ]
Returns an array with n elements removed from the beginning.app
Use
Array.slice()
to create a slice of the array withn
elements taken from the beginning.ideconst take = (arr, n = 1) => arr.slice(0, n);
返回一個由數組的前n
個元素組成的新數組。oop
用Array.slice()
建立一個新的數組,數組元素由指定數組的前n
個元素組成。rest
➜ code cat take.js const take = (arr, n = 1) => arr.slice(0, n); console.log(take([1, 2, 3], 5)); console.log(take([1, 2, 3], 0)); ➜ code node take.js [ 1, 2, 3 ] []
n
能夠指定爲0
,即一個也不取出。省略則n = 1
。
Returns an array with n elements removed from the end.
Use
Array.slice()
to create a slice of the array withn
elements taken from the end.const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
返回一個由數組的後n
個元素組成的新數組。
用Array.slice()
建立一個新的數組,數組元素由指定數組的後n
個元素組成。
➜ code cat takeRight.js const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); console.log(takeRight([1, 2, 3], 2)); console.log(takeRight([1, 2, 3])); ➜ code node takeRight.js [ 2, 3 ] [ 3 ]
拿數組後n
個元素只需從數組長度減去n
的位置開始取到結尾就能夠了,slice
第二個參數是能夠省略的,由於是取到最後一個元素。
Removes elements from the end of an array until the passed function returns
true
. Returns the removed elements.Loop through the array, using a
for...of
loop overArray.keys()
until the returned value from the function istrue
. Return the removed elements, usingArray.reverse()
andArray.slice()
.const takeRightWhile = (arr, func) => { for (let i of arr.reverse().keys()) if (func(arr[i])) return arr.reverse().slice(arr.length - i, arr.length); return arr; };
從數組尾部開始刪除元素,直到對數組元素運用指定方法fn
爲true
爲止。同時返回被刪除的元素。
循環數組,使用for…of
循環Array.keys()
直到對數組元素調用指定方法返回true
爲止。最後返回刪除的全部元素,過程當中結合了Array.reverse()
和Array.slice()
。
➜ code cat takeRightWhile.js const takeRightWhile = (arr, func) => { for (let i of arr.reverse().keys()) if(func(arr[i])) return arr.reverse().slice(arr.length - i, arr.length); return arr; }; console.log(takeRightWhile([1, 2, 3, 4], n => n < 3)); ➜ code node takeRightWhile.js [ 3, 4 ]
for (let i of arr.reverse().keys())
循環數組arr
的key
值,即索引,由於是reverse()
,因此是反向循環。如一個數組有五個元素,那麼i
就是4->3->2->1->0
這樣的順序。
if(func(arr[i])) return arr.reverse().slice(arr.length - i, arr.length);
對數組元素arr[i]
調用func
,若真,此時的i
就是順數的第一個該刪除的元素的索引,要刪除的元素就是今後直到數組結尾爲止;即arr.reverse().slice(arr.length - i, arr.length)
包含的索引元素。
return arr;
若是前面的整個遍歷過程當中func(arr[i])
都不爲true
的話,那就返回原數組,合情合理。
Removes elements in an array until the passed function returns
true
. Returns the removed elements.Loop through the array, using a
for...of
loop overArray.keys()
until the returned value from the function istrue
. Return the removed elements, usingArray.slice()
.const takeWhile = (arr, func) => { for (let i of arr.keys()) if (func(arr[i])) return arr.slice(0, i); return arr; };
從數組索引爲0
開始刪除元素,直到對數組元素運用指定方法fn
爲true
爲止。同時返回被刪除的元素。
➜ code cat takeWhile.js const takeWhile = (arr, fn) => { for (let i of arr.keys()) if(fn(arr[i])) return arr.slice(0, i); return arr; }; console.log(takeWhile([1, 2, 3, 4], n => n >= 3)); ➜ code node takeWhile.js [ 1, 2 ]
跟takeRightWhile
正好相反,並且還更容易理解。沒什麼可說的了。
Returns every element that exists in any of the two arrays once.
Create a
Set
with all values ofa
andb
and convert to an array.const union = (a, b) => Array.from(new Set([...a, ...b]));
返回兩個數組的並集(像集合的並集同樣,不包含重複元素)。
建立一個以a
和b
數組爲元素的集合並把它轉化成數組。
➜ code cat union.js const union = (a, b) => Array.from(new Set([...a, ...b])); console.log(union([1, 2, 3], [4, 3, 2])); ➜ code node union.js [ 1, 2, 3, 4 ]
我本身寫的以下:
const union = (a, b) => [...new Set([...a, ...b])];
直接用ES6
擴展運算符…
也能達到效果。
原理太簡單,建立a
和b
數組的集合天然把他們二者的重複元素去掉了。
Returns every element that exists in any of the two arrays once, after applying the provided function to each array element of both.
Create a
Set
by applying allfn
to all values ofa
. Create aSet
froma
and all elements inb
whose value, after applyingfn
does not match a value in the previously created set. Return the last set converted to an array.const unionBy = (a, b, fn) => { const s = new Set(a.map(v => fn(v))); return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); };
對兩個數組的元素分別調用指定方法後,返回以運行結果爲斷定基準的並集,並集是原始數組元素的並集而不是運行結果的並集。
建立一個a
數組調用fn
後的集合a1
。再建立一個以數組a
和對數組b
進行過濾全部存在於集合a1
中的元素後所剩餘元素組成的數組爲基準的集合。並把該集合轉換成最終的數組。
➜ code cat unionBy.js const unionBy = (a, b, fn) => { const s = new Set(a.map(v => fn(v))); return Array.from(new Set([...a, ...b.filter(v => !s.has(fn(v)))])); }; console.log(unionBy([2.1], [1.2, 2.3], Math.floor)); ➜ code node unionBy.js [ 2.1, 1.2 ]
const s = new Set(a.map(v => fn(v)));
首先得建立其中一個數組的集合s
。
b.filter(v => !s.has(fn(v)))
這裏就是把b
數組中全部存在於a
調用fn
後生成的集合s
的元素都刪除掉。這樣剩下的全部元素和a
數組再進行集合運算後再轉換成數組。就是咱們所須要的結果。
Returns every element that exists in any of the two arrays once, using a provided comparator function.
Create a
Set
with all values ofa
and values inb
for which the comparator finds no matches ina
, usingArray.findIndex()
.const unionWith = (a, b, comp) => Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
對兩個數組的元素分別調用指定比較方法後,返回以運行結果爲斷定基準的並集,並集是原始數組元素的並集而不是運行結果的並集。
➜ code cat unionWith.js const unionWith = (a, b, comp) => Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); console.log(unionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b))); ➜ code node unionWith.js [ 1, 1.2, 1.5, 3, 0, 3.9 ]
分主客體,這裏主體是前一個數組,即a
,表示數組a
的全部元素都會保留下來。而後循環數組b
,用findIndex
方法去把全部對a
和b
的元素調用comp
比較方法後的結果不存在於a
數組中的全部元素篩選出來。最後把篩選出來的全部元素和數組a
組成新數組後再進行集合運算並把運算結果轉化爲數組。那就是unionWith
的最終結果。
Returns all unique values of an array.
Use ES6
Set
and the...rest
operator to discard all duplicated values.const uniqueElements = arr => [...new Set(arr)];
數組去重。
➜ code cat uniqueElements.js const uniqueElements = arr => [...new Set(arr)]; console.log(uniqueElements([1, 2, 2, 3, 4, 4, 5])); ➜ code node uniqueElements.js [ 1, 2, 3, 4, 5 ]
結合ES6的擴展運算符…
和集合便很容易實現。
Creates an array of arrays, ungrouping the elements in an array produced by zip.
Use
Math.max.apply()
to get the longest subarray in the array,Array.map()
to make each element an array. UseArray.reduce()
andArray.forEach()
to map grouped values to individual arrays.const unzip = arr => arr.reduce( (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), Array.from({ length: Math.max(...arr.map(x => x.length)) }).map(x => []) );
對於給定的多個數組,返回一個新的二維數組,數組的第一個元素包含多個數組的第一個元素,數組的第二個元素包含多個數組的第二個元素,以此類推(即把zip方法分好組的數組逆向解組)。
使用Math.max.apply()
方法來獲取輸入數組的子數組元素個數的最大長度,使用Array.map()
來把每個元素建立成一個數組。而後使用Array.reduce()
和Array.forEach()
去把組裏的元素分別加到各自的數組中。
➜ code cat unzip.js const unzip = arr => arr.reduce((acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), Array.from({ length: Math.max(...arr.map(x => x.length)) }).map(x => []) ); console.log(unzip([['a', 1, true], ['b', 2, false]])); console.log(unzip([['a', 1, true], ['b', 2]])); ➜ code node unzip.js [ [ 'a', 'b' ], [ 1, 2 ], [ true, false ] ] [ [ 'a', 'b' ], [ 1, 2 ], [ true ] ]
Array.from({ length: Math.max(...arr.map(x => x.length)) }).map(x => [])
這就是reduce
的初始二維數組,用Array.from
來生成一個數組,而後再map(x => [])
成一個二維數組,那麼數組的長度怎麼定呢?由於被unzip
的原數組裏的元素多是長度不一樣的數組。那麼確定是以長度最長的那個爲準,這樣才能包含解組後的全部元素。這就是length: Math.max(...arr.map(x => x.length))
作的事。
對於reduce
裏的方法:
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc)
acc
是累加值,在遍歷過程當中會一直變化,val.forEach((v, i) => acc[i].push(v))
這是遍歷過程當中val
數組元素push
到累加acc
對應索引數組的方法。
舉個例子:
原數組arr = [[1, 2, 3], ['a', 'b']]
,在遍歷過程當中初始累加acc = [[], [], []]
(含有三個元素的數組)。
// 第一次 val = [1, 2, 3] acc = [[1], [2], [3]] // 第二次 val = ['a', 'b'] acc = [[1, 'a'], [2, 'b'], [3]] // 這也是最終結果
Creates an array of elements, ungrouping the elements in an array produced by zip and applying the provided function.
Use
Math.max.apply()
to get the longest subarray in the array,Array.map()
to make each element an array. UseArray.reduce()
andArray.forEach()
to map grouped values to individual arrays. UseArray.map()
and the spread operator (...
) to applyfn
to each individual group of elements.const unzipWith = (arr, fn) => arr .reduce( (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), Array.from({ length: Math.max(...arr.map(x => x.length)) }).map(x => []) ) .map(val => fn(...val));
對於給定的多個數組,返回一個新的二維數組,數組的第一個元素包含多個數組的第一個元素,數組的第二個元素包含多個數組的第二個元素,以此類推(即把zip方法分好組的數組逆向解組),在此基礎上對二維數組的每一個元素運行指定方法並返回。
使用Math.max.apply()
方法來獲取數組的子數組元素個數的最大長度,使用Array.map()
來把每個元素建立成一個數組。而後使用Array.reduce()
和Array.forEach()
去把組裏的元素分別加到各自的數組中。而後再結合 Array.map()
和ES6擴展運算符…
把前面生成的二維數組的每一個元素分別調用fn
方法。
➜ code cat unzipWith.js const unzipWith = (arr, fn) => arr.reduce((acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), Array.from({ length: Math.max(...arr.map(x => x.length)) }).map(x => []) ) .map(val => fn(...val)); console.log(unzipWith([[1, 10, 100], [2, 20, 200]], (...args) => args.reduce((acc, v) => acc + v, 0))); ➜ code node unzipWith.js [ 3, 30, 300 ]
unzipWith
就比unzip
多了一個對每一個二維數組元素調用指定fn
方法。即map(val => fn(...val))
。其它都和unzip
同樣,沒啥可說的了。看以上例子運行結果就知道了。