Array - 30 seconds of code

Array

收集自30 seconds of code数组片段,30秒内快速理解!有部分自己实现的片段。

  • [] initialize2DArray
  • [] initializeArrayWithRange
  • [] initializeArrayWithRangeRight
  • [] initializeArrayWithValues
  • [] initializeNDArray
  • [] drop
  • [] dropWhile
  • [] dropRight
  • [] dropRightWhile
  • [] all
  • [] any
  • [] allEqual
  • [] countOccurrences
  • [] difference
  • [] differenceBy
  • [] differenceWith
  • [] filterNonUnique
  • [] filterNonUniqueBy
  • [] findLast
  • [] findLastIndex
  • [] indexOfAll
  • [] intersection
  • [] intersectionBy
  • [] intersectionWith
  • [] isSorted
  • [] arrayTOCSV
  • [] bifurcate
  • [] chunk
  • [] compact
  • [] countBy
  • [] deepFlatten
  • [] everyNth
  • [] flatten
  • [] groupBy

all

数组所有值Return true,则为true,否则 false

const all = (arr, fn = Boolean) => arr.every(fn);
all([1,2,3]) // true
all([1,2,3], i => i > 2) // false

allEqual

数组所有值全部相等,则为true,否则 false

const allEqual = arr => arr.every(i => i === arr[0]) 
allEqual([1, 2, 3, 4, 5, 6]) // false
allEqual([1, 1, 1, 1]) // true

any

数组中存在任意一个满足条件,则为true,否则 false

const any = (arr, fn = Boolean) => arr.some(fn) 
any([0, 0, 1, 0]) // true
any([0, 1, 2, 0], x => x === 3) // false

arrayToCSV

将一个二维数组转换为逗号分隔值(CSV)字符串。

const arrayToCSV = (arr, delimiter = ',') => arr.map(i => i.join(delimiter)).join('\n') 
arrayToCSV([['a', 'b'], ['c', 'd']]) // '"a","b"\n"c","d"'
arrayToCSV([['a', 'b'], ['c', 'd']], ';') // '"a";"b"\n"c";"d"'

bifurcate

将值分为2组,如果值在过滤器中为true,将其添加到第一组,否则加到第二组中.
Use: Array.prototype.reduce() & Array.prototype.push()

const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[+!filter[i]].push(val), acc), [[], []]) 
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]) // [ ['beep', 'boop', 'bar'], ['foo'] ]

bifurcateBy

将值分为2组,如果值在过滤器函数中为true,将其添加到第一组,否则加到第二组中.
Use: Array.prototype.reduce() & Array.prototype.push()

const bifurcateBy = (arr, fn) => arr.reduce((acc, val) => (acc[+!fn(val)].push(val), acc), [[], []])
bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b') // [ ['beep', 'boop', 'bar'], ['foo'] ]

chunk

将数组组按照指定的大小分成多组。
Use: Array.from() & Array.prototype.slice()

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

删除数组中的空值(false, null, 0, “”, undefined, and NaN)
Use: Array.filter()

const compact = arr => arr.filter(Boolean)
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]) // [ 1, 2, 3, 'a', 's', 34 ]

countBy

根据给定函数,返回数组计数

const countBy = (arr, fn) => arr.map(v => typeof fn === 'function' ? fn(v) : v[fn])
  .reduce((acc, cur) => (acc[cur] = (acc[cur] || 0) + 1, acc), {})
countBy([6.1, 4.2, 6.3], Math.floor) // {4: 1, 6: 2}
countBy(['one', 'two', 'three'], 'length') // {3: 2, 5: 1}

countOccurrences

计数数组中出现的值

const countOccurrences = (arr, val) => arr.filter(v => v === val).length
countOccurrences([1, 1, 2, 1, 2, 3], 1) // 3

deepFlatten

扁平化多维数组

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

前数组与后者数组的不同项,输出同结果项的集合

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

differenceBy

前数组与后者数组通过过滤器函数比较,输出同结果项的集合

const differenceBy = (a, b, fn) => {
    const s = new Set(b.map(fn))
    return a.filter(x => !s.has(fn(x)))
}
differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor) // [1.2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x) // [ { x: 2 } ]

differenceWith

const differenceWith = (arr, val, fn) => arr.filter(x => !val.some(i => fn(x, i)))
differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)) // [1, 1.2]

drop

从左开始删除特定数量的数据,默认为1

const drop = (arr, size = 1) => arr.slice(size)
drop([1, 2, 3]) // [2,3]
drop([1, 2, 3], 2) // [3]
drop([1, 2, 3], 42) // []

dropRight

从右开始删除特定数量的数据,默认为1

const dropRight = (arr, size = 1) => arr.slice(0, -size)
dropRight([1, 2, 3]) // [2,3]
dropRight([1, 2, 3], 2) // [3]
dropRight([1, 2, 3], 42) // []

dropRightWhile

从右开始删除,直到返回 true

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

dropWhile

从左开始删除,直到返回 true

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

everyNth

提取每隔 n 个的元素,以数组返回。

const everyNth = (arr, func) => {
    while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1)
    return arr
}
everyNth([1, 2, 3, 4, 5, 6], 2) // [ 2, 4, 6 ]

filterNonUnique

过滤掉非唯一值的数组。

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

filterNonUniqueBy

过滤掉符合过滤器非唯一值的数组。

const filterNonUniqueBy = (arr, fn) => arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)))
filterNonUniqueBy(
  [
    { id: 0, value: 'a' },
    { id: 1, value: 'b' },
    { id: 2, value: 'c' },
    { id: 1, value: 'd' },
    { id: 0, value: 'e' }
  ],
  (a, b) => a.id == b.id
) // [ { id: 2, value: 'c' } ]