JavaScript30秒, 從入門到放棄

有意思

最近很火的github上的庫30-seconds-of-code,特別有意思,代碼也很優雅。javascript

  1. 能學es6
  2. 本身翻譯,能學英語
  3. 代碼很美,很優雅,美即正義
  4. 函數式表達,享受

arrayGcd

Calculates the greatest common denominator (gcd) of an array of numbers.java

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.node

const 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

arrayLcm

Calculates the lowest common multiple (lcm) of an array of numbers.github

Use Array.reduce() and the lcm 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算法,關鍵點是兩個數的最大公約數和最小公倍數的乘積正好就是這兩個數的乘積。

arrayMax

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()乾的事,沒啥可說的了。

arrayMin

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()乾的事,沒啥可說的了。

chunk

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. Use Array.slice() to map each element of the new array to a chunk the length of size. 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
複製代碼

compact

Removes falsey values from an array.

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

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()falsenull0""undefinedNaN這些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()乾的,沒啥好說。

countOccurrences

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

deepFlatten

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秒, 從入門到放棄

相關文章
相關標籤/搜索