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]
的直接结果。其他都是同样的。这也很好理解了。