最近很火的github
上的库30-seconds-of-code
,特别有意思,代码也很优雅。javascript
Calculates the greatest common denominator (gcd) of an array of numbers.java
Use
Array.reduce()
and thegcd
formula (uses recursion) to calculate the greatest common denominator of an array of numbers.nodeconst arrayGcd = arr =>{ const gcd = (x, y) => !y ? x : gcd(y, x % y); return arr.reduce((a,b) => gcd(a,b)); } // arrayGcd([1,2,3,4,5]) -> 1 // arrayGcd([4,8,12]) -> 4 复制代码
计算数组的最大公约数。python
使用Array.reduce()
和gcd
公式(使用递归)来计算一个数组的最大公约数。git
➜ code cat arrayGcd.js
const arrayGcd = arr => {
const gcd = (x, y) => !y ? x : gcd(y, x % y);
return arr.reduce((a, b) => gcd(a, b));
}
console.log(arrayGcd([1, 2, 3, 4, 5]));
console.log(arrayGcd([4, 8, 12]));
➜ code node arrayGcd.js
1
4
复制代码
gcd
即欧几里德算法,具体不表,自查。这里用到了数组的reduce方法,至关简洁,reduce不太了解的话,看下mdn就明白。es6
Calculates the lowest common multiple (lcm) of an array of numbers.github
Use
Array.reduce()
and thelcm
formula (uses recursion) to calculate the lowest common multiple of an array of numbers.算法const arrayLcm = arr =>{ const gcd = (x, y) => !y ? x : gcd(y, x % y); const lcm = (x, y) => (x*y)/gcd(x, y) return arr.reduce((a,b) => lcm(a,b)); } // arrayLcm([1,2,3,4,5]) -> 60 // arrayLcm([4,8,12]) -> 24 复制代码
计算一个数组的最小公倍数。数组
使用Array.reduce()
和lcm
公式(使用递归)来计算一个数组的最大公约数。bash
➜ code cat arrayLcm.js
const arrayLcm = arr => {
const gcd = (x, y) => (!y ? x : gcd(y, x % y));
const lcm = (x, y) => x * y / gcd(x, y);
return arr.reduce((a, b) => lcm(a, b));
};
console.log(arrayLcm([1, 2, 3, 4, 5]));
console.log(arrayLcm([4, 8, 12]));
➜ code node arrayLcm.js
60
24
复制代码
lcm
算法用到了前面的gcd
算法,关键点是两个数的最大公约数和最小公倍数的乘积正好就是这两个数的乘积。
Returns the maximum value in an array.
Use
Math.max()
combined with the spread operator (...
) to get the maximum value in the array.const arrayMax = arr => Math.max(...arr); // arrayMax([10, 1, 5]) -> 10 复制代码
返回数组中最大的值。
使用Math.max()
和ES6
的扩展运算符…
返回数组中最大的值。
➜ code cat arrayMax.js
const arrayMax = arr => Math.max(...arr);
console.log(arrayMax([10, 1, 5]));
➜ code node arrayMax.js
10
复制代码
实际上就是Math.max()
干的事,没啥可说的了。
Returns the minimum value in an array.
Use
Math.min()
combined with the spread operator (...
) to get the minimum value in the array.const arrayMin = arr => Math.min(...arr); // arrayMin([10, 1, 5]) -> 1 复制代码
返回数组中最小的值。
使用Math.min()
和ES6
的扩展运算符…
返回数组中最小的值。
➜ code cat arrayMin.js
const arrayMin = arr => Math.min(...arr);
console.log(arrayMin([10, 1, 5]));
➜ code node arrayMin.js
1
复制代码
实际上就是Math.min()
干的事,没啥可说的了。
Chunks an array into smaller arrays of a specified size.
Use
Array.from()
to create a new array, that fits the number of chunks that will be produced. UseArray.slice()
to map each element of the new array to a chunk the length ofsize
. If the original array can't be split evenly, the final chunk will contain the remaining elements.const chunk = (arr, size) => Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size)); // chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]] 复制代码
按照给定的size
将一个数组切分红含有size
个数的更小数组块的数组。
使用Array.from()
生产新的符合定义的数组。使用Array.slice()
来截取指定size
个元素组成新的数组块。若是原数组长度不能被size
整除,最后的剩余的那些元素将归属于最后一个块。
➜ code cat chunk.js
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
console.log(chunk([1, 2, 3, 4, 5], 2));
➜ code node chunk.js
[ [ 1, 2 ], [ 3, 4 ], [ 5 ] ]
复制代码
Array.from(arrayLike, mapFn, thisArg)
这个方法呢,第一个参数是一个类数组或者可迭代的对象,第二个参数是一个应用在每个数组元素上的方法,第三个参数就是改变this
的指向了。通俗说就是指定谁是你的爸爸。
这里用了一个{ length: Math.ceil(arr.length / size) }
迭代对象,length
指定了迭代次数,它正好按照size
分块后的数组长度正好就是原数组长度除以size
向上取整的值。向上取整就是为了知足不能彻底整除的状况。好比5个元素按照2个进行分块,分了两块两个元素的,剩最后一个元素成了独立块,总共3个元素。
(v, i)
,因为迭代的时候数组在每个位置上都是以undefined
初始化的,因此v
一直都是undefined
。
arr.slice(i * size, i * size + size)
迭代过程当中每次截取size
个数的元素组成新数组。这里的i
就是随着迭代变化,好比length
是3,i
就是0,1,2。
这里的迭代相似python
里的range
。
➜ code python
Python 3.6.4 (default, Dec 23 2017, 10:37:40)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> arr = [1,2,3,4,5]
>>> size = 2
>>> for i in range(math.ceil(len(arr) / size)):
... print('index: ', i)
...
index: 0
index: 1
index: 2
复制代码
Removes falsey values from an array.
Use
Array.filter()
to filter out falsey values (false
,null
,0
,""
,undefined
, andNaN
).const compact = arr => arr.filter(Boolean); // compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ] 复制代码
移除掉数组里falsey
的元素。(这个falsey
不太好翻译,我记得好像不是错误的,应该是该值布尔运算值为false
的,我我的经常使用!!
进行运算)。
使用Array.filter()
把false
、null
、0
、""
、undefined
和NaN
这些falsey
过滤掉。
➜ code cat compact.js
const compact = arr => arr.filter(Boolean);
console.log(compact([0, 1, false, 2, "", 3, "a", "e" * 23, NaN, "s", 34]));
➜ code node compact.js
[ 1, 2, 3, 'a', 's', 34 ]
复制代码
Array.prototype.filter()
干的,没啥好说。
Counts the occurrences of a value in an array.
Use
Array.reduce()
to increment a counter each time you encounter the specific value inside the array.const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0); // countOccurrences([1,1,2,1,2,3], 1) -> 3 复制代码
统计一个元素在一个数组中出现的次数。
使用Array.reduce()
在遍历过程当中若是指定元素在数组中出现,则增长它的次数值,默认次数为0。
➜ code cat countOccurrences.js
const countOccurrences = (arr, value) =>
arr.reduce((a, v) => (v === value ? a + 1 : a + 0), 0);
console.log(countOccurrences([1, 1, 2, 1, 2, 3], 1));
console.log(countOccurrences([1, 1, 2, 1, 2, 3], 5));
➜ code node countOccurrences.js
3
0
复制代码
三元运算符(v === value ? a + 1 : a + 0)
遍历过程当中判断遍历数组值v
是否严格等于指定值value
,是,次数a+1
;否,a+0
。
最后的一个逗号后面的0,是这个初始值,即a=0
,这个懂reduce
方法都知道,特别指出是,由于这个函数必定会有返回值,若是指定元素没有在数组中出现一次,返回值是0
,因此必须得初始化为0
。
Deep flattens an array.
Use recursion. Use
Array.concat()
with an empty array ([]
) and the spread operator (...
) to flatten an array. Recursively flatten each element that is an array.const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v)); // deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] 复制代码
深度摊平一个数组。
使用递归方法。结合Array.concat()
、空数组[]
和ES6
的扩展运算符…
来摊平一个数组,若是摊平的元素仍是一个数组,就再递归运用该方法。
➜ code cat deepFlatten.js
const deepFlatten = arr =>
[].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
console.log(deepFlatten([1, [2], [[3], 4], 5]));
➜ code node deepFlatten.js
[ 1, 2, 3, 4, 5 ]
复制代码
三元运算符(Array.isArray(v) ? deepFlatten(v) : v)
判断v
是不是一个数组,是,返回递归运用deepFlatten(v)
后的值;否,直接返回v
。
[].concat(...arr.map(fn))
用空数组把map
运算产生的数组进行…
扩展运算值拼接成结果数组返回。
该方法是深度摊平方法,在不少时候还有特定的摊平一层的需求,underscore
就有。实现的方法就是再加一个标志参数进行处理便可。具体不讲了。
应该会写一个系列,今天先写到这,明天继续。
我的翻译水平有限,欢迎你们在issues上批评指正。JavaScript30秒, 从入门到放弃