30-seconds-code——Array

英文文章來源于:https://github.com/Chalarangelo/30-seconds-of-code/blob/master/README.md

Array

數組最大公約數 (arrayGcd)

計算數字數組最大公約數 (gcd).

Array.reduce()gcd 運算式 (使用遞歸) 計算一個數字數組的最大公約數.

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

數組最小公倍數 (arrayLcm)

求數字數組的最小公倍數 (lcm).

Array.reduce()lcm 運算式 (使用遞歸) 計算一個數字數組的最小公倍數.

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

arrayMax

返回一個數組中的最大值。

使用 Math.max() 結合spread操作符 (...) 去獲取數組中的最大值.

const arrayMax = arr => Math.max(...arr);
// arrayMax([10, 1, 5]) -> 10

arrayMin

返回數組中的最小值.

Math.min() 集合spread操作符 (...) 去獲取數組中的最小值.

const arrayMin = arr => Math.min(...arr);
// arrayMin([10, 1, 5]) -> 1

chunk

將一個數組分成指定長度的塊數組.

Array.from() 生成一個適當長度的塊數組,然后遍歷整個塊數組.
Array.slice() 分割原數組向塊數組中的塊中插入元素,塊的長度為 size.
如果原數組最終不能在進行分割,那么這個塊將包含剩余的所有元素.

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]]

compact

將數組中的非真值移除.

Array.filter() 去移除非真值 (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 ]

注:Boolean的初始值為false

countOccurrences

計算一個值在數組中出現的次數.

Array.reduce() 去計算每次遇到的特定值的次數.

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
// countOccurrences([1,1,2,1,2,3], 1) -> 3

deepFlatten

抹平數組(沒有嵌套的數組).

使用遞歸.
Array.concat() 拼接一個空數組 ([]) 然后使用spread操作符 (...) 去抹平數組.

const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]

difference

返回的數組中元素來自于源數組,但不包含目標數組中的元素.

將目標數組轉化為一個 Set, 然后用 Array.filter() 過濾原數組返回不在目標數組中的元素.

const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
// difference([1,2,3], [1,2,4]) -> [3]
const difference2 = (a, b) => a.filter(x => b.indexOf(x) === -1)
// difference2([1,2,3], [1,2,4]) -> [3]
const difference2 = (a, b) => a.filter(x => !b.includes(x))
// difference2([1,2,3], [1,2,4]) -> [3]

differenceWith

返回的數組中元素來自于源數組和目標數組中的元素經過comp后的元素.

Array.filter()Array.find() 去找出合適的元素.

const differenceWith = (res, dest, comp) => res.filter(a => !dest.find(b => comp(a, b)))
// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]

distinctValuesOfArray

數組去重.

用 ES6 Set...rest 操作符去除所有重復的元素.

const distinctValuesOfArray = arr => [...new Set(arr)];
// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]

dropElements

移除數組中的元素直到func返回 true,返回使數組中剩余的元素.

循環數組, 判斷func是否返回 true,如果否使用 Array.slice() 移除數組中的第一個元素,直到 function 返回 true; 否則,直接返回數組.

const dropElements = (arr, func) => {
  while (arr.length > 0 && !func(arr[0])) arr.splice(0,1);
  return arr;
};
// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
const dropElements = (arr, func) => {
  while (arr.length > 0 && !func(arr[0])) arr.splice(0, 1);
  return arr;
};
dropElements([4, 3, 2, 1], n => n >= 3)

移除數組中的元素如果func返回 true

使用 Array.filter()來進行數組過濾

const dropElements = (arr, func) => arr.filter(!func)
dropElements([4, 3, 2, 1], n => n >= 3)

dropRight

返回一個從用變去除 n 個元素的數組

如果 n 小于數組的長度用 Array.slice() 去分割數組,然后返回分割得到的數組,否則返回一個空數組.

const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
// dropRight([1,2,3]) -> [1,2]
// dropRight([1,2,3], 2) -> [1]
// dropRight([1,2,3], 42) -> []
const dropRight = (arr, n = 1) => n < arr.length ? arr.splice(0, arr.length - n) : []
// dropRight([1,2,3])

everyNth

每遍歷 n 個元素,返回一個元素.

Array.filter() 去篩選出一個數組,篩選條件是每遍歷 n 個元素,返回一個元素.

const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
// everyNth([1,2,3,4,5,6], 2) -> [ 2, 4, 6 ]

filterNonUnique

過濾移除數組中重復出現的元素.

Array.filter() 保留數組中獨一無二的元素.

const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]

flatten

抹平數組.

用一個空數組和spread ... 操作符來生成一個沒有嵌套的數組.

const flatten = arr => [].concat( ...arr );
// flatten([1,[2],3,4]) -> [1,2,3,4]

flattenDepth

抹平數組取決于指定的值 depth.

通過遞減 depth,然后使用遞歸來完成.
Array.reduce()Array.concat() 來合并元素或者數組.
默認 depth 值為 1 時停止遞歸.
省略定義 depth,將返回數組本身.

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), []);
// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]

groupBy

根據給定的函數來對數組中的元素進行分組.

Array.map() 依據 func 來遍歷數組中的元素.
Array.reduce() 創建一個對象, 對象中的key是map的結果.

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; }, {});
// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}

head

返回數組中的第一個元素.

arr[0] 返回傳入數組的第一個元素.

const head = arr => arr[0];
// head([1,2,3]) -> 1

initial

返回數組中出最后一個外的所有元素.

arr.slice(0,-1) 來實現.

const initial = arr => arr.slice(0, -1);
// initial([1,2,3]) -> [1,2]

initialize2DArray

通過傳入寬高和默認值來初始化一個二維數組.

Array.map() 去生成一個 h 列, 每列是一個長度為 w,默認值是 value的數組的二維數組. 如果默認值沒有提供,那么默認值就為 null.

const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]

initializeArrayWithRange

初始化一個數組,這個數組包含限定范圍的數字 startend.

Array.from((end + 1) - start) 去創建一個長度為end - start + 1的數組,然后用Array.map() 為初始化的數組賦值.
你可以省略 start,它的默認值是 0.

const initializeArrayWithRange = (end, start = 0) => 
  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]

initializeArrayWithValues

初始化一個長度為 n 數組,默認值為 value 的數組.

Array(n) 去創建一個長度為n,元素值為空的數組,然后用 fill(v) 為每個元素賦值為 value.
如果省略 value ,元素的默認值為 0.

const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]

intersection

返回兩個數組的共有元素.

b 轉換為一個集合 Set , 然后用 Array.filter() 過濾掉 a 中包含 b 中的元素.

const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
// intersection([1,2,3], [4,3,2]) -> [2,3]

last

返回數組中的最后一個元素.

arr.length - 1 作為給定數組最后一個元素的索引,返回該索引位置的元素.

const last = arr => arr[arr.length - 1];
// last([1,2,3]) -> 3

mapObject

用一個函數作為映射規則,將數組轉化為一個對象, 對象的鍵值對由原始的的的值作為鍵,映射得到的值作為值.

使用內部匿名函數的作用域去聲明一個undefined的內存空間, 用閉包去存儲返回值. 用一個新 Array 存儲原數組和經過 fn 映射的結果,然后用 , 操作符實現下一步的return操作, 無需上下文的切換 (由于閉包和操作順序).

const mapObject = (arr, fn) => 
  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,i) => (acc[val] = a[1][i], acc), {}) )) ();
/*
const squareIt = arr => mapObject(arr, a => a*a)
squareIt([1,2,3]) // { 1: 1, 2: 4, 3: 9 }
*/

nthElement

返回數組中的第 n 個元素.

Array.slice() 去獲得包含第 n 個元素的數組,數組長度為1.
如果索引超出數組范圍,返回一個 [].
如果省略參數 n, 默認的獲取數組的第一個元素.

const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n,n+1) : arr.slice(n))[0];
// nthElement(['a','b','c'],1) -> 'b'
// nthElement(['a','b','b'],-3) -> 'a'

pick

從對象中篩選出arr中指定的鍵值對.

Array.reduce() 去過濾并挑選出對象中所包含的鍵的鍵值對.

const pick = (obj, arr) =>
  arr.reduce((acc, cur) => (cur in obj && (acc[cur] = obj[cur]), acc), {});
// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }

pull

去除數組中的指定值.

Array.filter()Array.includes() 清除數組中不需要的值.
Array.length = 0 初始化數組,然后用arr.push()放入過濾后剩余的數組元素 pulled.

const pull = (arr, ...args) => {
  let argState = Array.isArray(args[0]) ? args[0] : args;
  let pulled = arr.filter((v, i) => !argState.includes(v));
  arr.length = 0; 
  pulled.forEach(v => arr.push(v));
};

// let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c'];
// pull(myArray1, 'a', 'c');
// console.log(myArray1) -> [ 'b', 'b' ]

// let myArray2 = ['a', 'b', 'c', 'a', 'b', 'c'];
// pull(myArray2, ['a', 'c']);
// console.log(myArray2) -> [ 'b', 'b' ]

pullAtIndex

過濾出指定索引的數組元素,并修改原數組.

Array.filter()Array.includes() 提取不需要的元素.
Array.length = 0 初始化數組且長度為零, 用 Array.push() 重新傳入剩余的元素.
Array.push() 記錄pulled值

const pullAtIndex = (arr, pullArr) => {
  let removed = [];
  let pulled = arr.map((v, i) => pullArr.includes(i) ? removed.push(v) : v)
                  .filter((v, i) => !pullArr.includes(i))
  arr.length = 0; 
  pulled.forEach(v => arr.push(v));
  return removed;
}

// let myArray = ['a', 'b', 'c', 'd'];
// let pulled = pullAtIndex(myArray, [1, 3]);

// console.log(myArray); -> [ 'a', 'c' ]
// console.log(pulled); -> [ 'b', 'd' ]

pullAtValue

從原數組中過濾出指定元素. 返回過濾出的元素.

Array.filter()Array.includes() 移除不必要的元素.
Array.length = 0 初始化元素組且長度為零,用 Array.push() 重新傳入剩余的元素.
Array.push() 記錄 pulled 值

const pullAtValue = (arr, pullArr) => {
  let removed = [], 
    pushToRemove = arr.forEach((v, i) => pullArr.includes(v) ? removed.push(v) : v),
    mutateTo = arr.filter((v, i) => !pullArr.includes(v));
  arr.length = 0;
  mutateTo.forEach(v => arr.push(v));
  return removed;
}
/*
let myArray = ['a', 'b', 'c', 'd'];
let pulled = pullAtValue(myArray, ['b', 'd']);
console.log(myArray); -> [ 'a', 'c' ]
console.log(pulled); -> [ 'b', 'd' ]
*/
const pullAtValue = (arr, pullArr) => {
  let removed = []; 
  arr.forEach((v, i) => pullArr.includes(v) ? removed.push(v) : v);
  pullArr.filter((v) => arr.splice(arr.indexOf(v), 1));
  return removed;
}
/*
let myArray = ['a', 'b', 'c', 'd'];
let pulled = pullAtValue(myArray, ['b', 'd']);
console.log(myArray); -> [ 'a', 'c' ]
console.log(pulled); -> [ 'b', 'd' ]
*/

remove

如果給定的函數返回 false, 則從數組中移除元素.

Array.filter() 找返回 false 的數組元素,用 Array.reduce()Array.splice() 對原數組進行處理.
func 調用 (value, index, array) 參數.

const remove = (arr, func) =>
  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
    arr.splice(arr.indexOf(val), 1);
    return acc.concat(val);
  }, []) : [];
// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]

sample

從數組中返回一個隨機元素.

Math.random() 生成一個隨機數, 乘以數組的 length ,然后 Math.floor() 進行下舍入.
這個方法也適合字符串.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];
// sample([3, 7, 9, 11]) -> 9

similarity

返回一個數組,數組元素在兩個給定的數組中均有.

filter()過濾出不在另一個數組中的 values, 確定條件用 includes().

const similarity = (arr, values) => arr.filter(v => values.includes(v));
// similarity([1,2,3], [1,2,4]) -> [1,2]

symmetricDifference

返回一個數組,包含在給定的兩個數組中均未出現的元素.

為每個數組創建一個 Set , 然后用 Array.filter() 過濾剩下都有的元素.

const symmetricDifference = (a, b) => {
  const sA = new Set(a), sB = new Set(b);
  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
}
// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
const symmetricDifference = (a, b) => [...(new Set([...a,...b]))].filter((v) => !a.includes(v) || !b.includes(v));
// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]

shuffle

隨機化一個數組值的順序.

Array.sort() 重新排序數組 , 用 Math.random() 作比較器.

const shuffle = arr => arr.sort(() => Math.random() - 0.5);
// shuffle([1,2,3]) -> [2,3,1]

tail

返回數組中出第一個元素外的所有元素.

如果,數組 length 大于 1 返回 arr.slice(1),否者,返回整個數組.

const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
// tail([1,2,3]) -> [2,3]
// tail([1]) -> [1]

take

返回指定長度的數組,數組中元素從數組第一個元素起.

Array.slice() 從原始數組的第一個元素起,截取 n 個元素.

const take = (arr, n = 1) => arr.slice(0, n);
// take([1, 2, 3], 5) -> [1, 2, 3]
// take([1, 2, 3], 0) -> []

takeRight

返回指定長度的數組,數組中元素從數組最后一個元素起.

Array.slice() 從原始數組的最后一個元素起,截取 n 個元素.

const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
// takeRight([1, 2, 3]) -> [3]

union

返回兩個數組中存在的所有元素.

創建一個 Setab 所有元素,然后轉換為數組.

const union = (a, b) => Array.from(new Set([...a, ...b]));
// union([1,2,3], [4,3,2]) -> [1,2,3,4]

without

從數組中移除所有指定的元素.

Array.filter() 過濾出所有制定的元素(用 !Array.includes() 做過濾條件 ).

(For a snippet that mutates the original array see pull)

const without = (arr, ...args) => arr.filter(v => !args.includes(v));
// without([2, 1, 2, 3], 1, 2) -> [3]

zip

創建一個數組,根據原始數組中的位置進行分組.

Math.max.apply() 獲得參數中最長的數組的長度.
創建一個用該長度做返回值并使用 array.frommap() 創建分組的元素數組.
如果參數數組的長度不同, undefined 將被用于沒有元素的地方.

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]);
  })
}
//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]

zipObject

給定一個有效的屬性標識數組,返回一個屬性與值相關聯的對象.
因為對象可以有未定義的值,但不能有未定義的屬性指針,所以使用 Array.reduce() 決定結果對象的結構.

const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}

更多關于30-seconds-code中文翻譯
https://github.com/lvzhenbang/article/blob/master/js/30-seconds-code/index.md

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容

  • PHP數組函數,摘錄于PHP手冊 1、array_change_key_case (PHP 4 >= 4.2.0,...
    kotlin360閱讀 720評論 2 1
  • php usleep() 函數延遲代碼執行若干微秒。 unpack() 函數從二進制字符串對數據進行解包。 uni...
    思夢PHP閱讀 1,993評論 1 24
  • PHP常用函數大全 usleep() 函數延遲代碼執行若干微秒。 unpack() 函數從二進制字符串對數據進行解...
    上街買菜丶迷倒老太閱讀 1,376評論 0 20
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,775評論 18 139
  • 數組是一種可變的、可索引的數據集合。在Scala中用Array[T]的形式來表示Java中的數組形式 T[]。 v...
    時待吾閱讀 958評論 0 0