30 seconds of code - array 中文简要说明

章承基
2023-12-01

all

const all = (arr, fn = Boolean) => arr.every(fn)

函数封装了every函数,判断条件默认为元素默认转为boolean值,如果都为true,则返回true。否则,返回false。

allEuqual

const allEqual = arr => arr.every(val => val === arr[0])

如all函数函数,判断条件变为数组元素是否都与数组第一项相同,

any

const any = (arr, fn = Boolean) => arr.some(fn)

any函数封装some,只要数组元素有一个转为true,则返回true。

arrayToCSV

const arrayToCSV = (arr, delimiter = ',') =>
  arr
    .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter))
    .join('\n');

    arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
    arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'
    arrayToCSV([['a', '"b" great'], ['c', 3.1415]]); // '"a","""b"" great"\n"c",3.1415'

delimiter是分隔符.讲二维数组转换为特定格式的字符串。

bifurcate

const bifurcate = (arr, filter) =>
  arr.reduce(
    (acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc),
    [[], []]
  )

bifurcate是分叉。filter是一个boolean数组。该函数创建一个新数组,若干arr的元素对应的boolean数组元素为true,则被push进新数组的第一项。否则,则被push进新数组的第二项。

(acc[filter[i] ? 0 : 1].push(val), acc)

使用了逗号运算符,隐式return了acc。

bifurcateBy

const bifurcateBy = (arr, fn) => 
  arr.reduce((acc, cur, i) => (acc[fn(cur) ? 0 : 1].push(cur), acc), [[],[]])
let result = bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b')

如bifurcate函数一样,只是将判断条件换位fn。

chunk

const chunk = (arr, size) =>
  Array.from({length: Math.ceil(arr.length / size)}, (value, index) => arr.slice(index * size, index * size+ size))

chunk是分块。这里巧妙了用了Array.from的第二个参数mapFn,新数组的每个元素都是arr的制定子集。

compact

const compact = arr =>  arr.filter(Boolean)

filter去除falsey values(可以转换为false的值) (false, null, 0, “”, undefined, and NaN)。

countBy

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

该方法返回一个新对象acc。当fn是一个函数时,arr的所有元素调用这个函数。若fn不是函数,则调用该类型的原型上的自带的属性,如String.prototype.length。acc[val] || 0,当第一个操作数为false时,就会返回 0,若是true则返回acc的value。

countOccurrences

const countOccurrences = (arr, val) => arr.reduce((acc, cur) => (cur === val ? acc + 1 : acc), 0)

console.log(countOccurrences([1, 1, 2, 1, 2, 3], 1))

统计数组中指定元素val的出现次数

deepFlatten

const deepFlatten = arr => [].concat(...arr.map(val => Array.isArray(val) ? deepFlatten(val) :  val))

多维数组使用…扩展运算符和concat()扁平化为一维数组

diffence

const diffence = (a, b) => {
  const s = new Set(b)
  return a.filter(x => !s.has(x))
}

使用Set返回存在于a,但不存在b的元素

diffenceBy

const diffence = (a, b, fn) => {
  const s = new Set(b.map(fn))
  return a.map(fn).filter(el => !s.has(el))
}

跟diffence相似,只是a,b元素先全部调用fn,转换为新数组。

diffenceWith

const diffenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1)

differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2]

这个函数对我来说也是相当有难度的。首先,arr是要被过滤的数组,val是与之比较的数组,comp是比较函数。findIndex作用是返回第一个符合comp函数的arr数组元素的索引值,如果都不符合则返回-1。根据arr数组中的不同元素a

val.findIndex(b => comp(a, b)) === -1

会有true或者false值,从而进行filter。

drop

const drop = (arr, n = 1) => arr.slice(n)

从数组开头删除n位元素

dropRight

const dropRight = (arr, n = 1) => arr.slice(0, n)

从数组末尾删除n位元素

dropRightWhile

const dropRightWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[arr.length - 1])) 
    arr.slice(0, -1)
  return arr
}

从数组右边开始删除元素,不过判断条件变为func。一直删除到数组右边直至遇到能让func变为true的元素。

dropWhile

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

从数组左边开始删除元素,判断条件变为func。一直删除到数组左边直至遇到能让func变为true的元素。

everyNth

const everyNth = (arr, nth) =>  arr.filter((e, i) => i % nth === nth - 1)

返回一个新数组,此数组的元素是arr的第 n * nth个元素(n是自然数)

filterFalsy

const filterFalsy = arr => arr.filter(Boolean)

去除数组中能转换为false的元素。

filterNonUnique

const filterNonUnique = arr => arr.filter(v => arr.indexOf(v) === arr.lastIndexOf(x))

保留数组中互不相同的元素

filterNonUniqueBy

const filterNonUniqueBy = (arr, fn) => arr.filter((v, i) => arr.every((v, j) => (i === j) === fn(v, x, i, j)))

扩展了filterNonUnique方法,通过方法fn进行判断。fn四个参数是比较两个元素的值和索引(方便fn方法的扩展)

(i === j) === fn(v, x, i, j)

注意arr.every(),当数组内所有索引和值比较过,都为true,那个元素才是独一无二的(unique)。

findLast

const findLast = (arr, fn) => arr.filter(fn).pop()

寻找数组最后一个能满足fn的元素

findLastIndex

const findLastIndex = (arr, fn) => {
  arr.map((v,i) => [i, v])
    .filter(([i, v]) => fn(v, i, arr))
    .pop()[0]
}
arr.map((v,i) => [i, v])

这句改变了arr数组的元素,现在它的每个元素是[i, v](数组),注意filter的形参用了[i, v]表示。

flatten

const flatten = (arr, depth = 1) => arr.reduce((acc, cur) => acc.concat(depth > 1 && Array.isArray(cur) ? flatten(cur, depth - 1) : cur), [])

用depth记录并判断扁平化的层数。注意,这次flatten,用了reduce和concat()

forEachRight

const forEachRight = (arr, callback) => arr.slice(0).reverse().forEach(callback)

复制一个新数组然后reverse,再使用forEach

groupBy

const groupBy = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).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']}

数组的元素调用fn,将其结果保存到一个对象中。

acc[val] = (acc[val] || []).concat(arr[i])

acc[val]为undefined则返回[],使得acc[val]的值为一个数组。

 类似资料: