const all = (arr, fn = Boolean) => arr.every(fn)
函数封装了every函数,判断条件默认为元素默认转为boolean值,如果都为true,则返回true。否则,返回false。
const allEqual = arr => arr.every(val => val === arr[0])
如all函数函数,判断条件变为数组元素是否都与数组第一项相同,
const any = (arr, fn = Boolean) => arr.some(fn)
any函数封装some,只要数组元素有一个转为true,则返回true。
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是分隔符.讲二维数组转换为特定格式的字符串。
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。
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。
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的制定子集。
const compact = arr => arr.filter(Boolean)
filter去除falsey values(可以转换为false的值) (false, null, 0, “”, undefined, and NaN)。
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。
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的出现次数
const deepFlatten = arr => [].concat(...arr.map(val => Array.isArray(val) ? deepFlatten(val) : val))
多维数组使用…扩展运算符和concat()扁平化为一维数组
const diffence = (a, b) => {
const s = new Set(b)
return a.filter(x => !s.has(x))
}
使用Set返回存在于a,但不存在b的元素
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,转换为新数组。
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。
const drop = (arr, n = 1) => arr.slice(n)
从数组开头删除n位元素
const dropRight = (arr, n = 1) => arr.slice(0, n)
从数组末尾删除n位元素
const dropRightWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[arr.length - 1]))
arr.slice(0, -1)
return arr
}
从数组右边开始删除元素,不过判断条件变为func。一直删除到数组右边直至遇到能让func变为true的元素。
const dropWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[0]))
arr.slice(1)
return arr
}
从数组左边开始删除元素,判断条件变为func。一直删除到数组左边直至遇到能让func变为true的元素。
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1)
返回一个新数组,此数组的元素是arr的第 n * nth个元素(n是自然数)
const filterFalsy = arr => arr.filter(Boolean)
去除数组中能转换为false的元素。
const filterNonUnique = arr => arr.filter(v => arr.indexOf(v) === arr.lastIndexOf(x))
保留数组中互不相同的元素
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)。
const findLast = (arr, fn) => arr.filter(fn).pop()
寻找数组最后一个能满足fn的元素
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]表示。
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()
const forEachRight = (arr, callback) => arr.slice(0).reverse().forEach(callback)
复制一个新数组然后reverse,再使用forEach
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]的值为一个数组。