原文地址: 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
同样,没啥可说的了。看以上例子运行结果就知道了。