原文连接: 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,以为还行的话,点个赞再走呗。。。