Open Lenny-Hu opened 5 years ago
const allEqual = arr => arr.every(val => val === arr[0]);
allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true
const any = (arr, fn = Boolean) => arr.some(fn);
any([0, 1, 2, 0], x => x >= 2); // true
any([0, 0, 1, 0]); // true
any([0, 0, 0, 0]); // false
some()
方法测试是否至少有一个元素通过由提供的函数实现的测试
var array = [1, 2, 3, 4, 5];
var even = function(element) { // checks whether an element is even return element % 2 === 0; };
console.log(array.some(even)); // expected output: true
csv
格式字符串const arrayToCSV = (arr, delimiter = ',') =>
arr
.map(v => v.map(x => (isNaN(x) ? `"${String(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'
arrayToCSV([['a,', 'b'], ['c', 'd']]); // ""a,","b" \n "c","d""
arrayToCSV([[NaN, 'a', 'b'], ['c', 'd']]); // ""NaN","a","b" \n "c","d""
arrayToCSV([[{}, 'a', 'b'], ['c', 'd']]); // ""[object Object]","a","b" \n "c","d""
isNaN
进行判断?判断值能否转换为数字,如果不可以,则在该值两侧加
""
(两侧添加双引号处理值内部有,
号的情况)或者在值内部有双引号的地方再添加一个双引号进行转义;最终让文件能被excel正常打开 isNaN运算实际过程是这样的:isNaN(Number(item))
例子1中,数组中的值为'
单引号,为何结果被双引号包围?
在
JavaScript
中,运算时认为字符串两侧的是双引号,例如'sbc'.replace(/"/, '""')
输出"sbc"
最后两个例子是为了测试传非 字符串或正常数字类型
时,不会报错,这也就是 String(x)
的作用
map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果
var array1 = [1, 4, 9, 16];
// pass a function to map const map1 = array1.map(x => x * 2);
console.log(map1); // expected output: Array [2, 8, 18, 32]
2
的二维数组,数组元素运算结果为true
的在前面,否则在后面const bifurcate = (arr, filter) =>
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ]
Array.prototype.reduce(callback[, initialValue])
方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值
callback
有accumulator
、currentValue
、currentIndex
、array
四个参数,accumulator
为累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue;在上面的例子中,accumulator 为传参进去的二维数组,运算的结果都被添加到了这个二维数组里面。reduce参考
Array.prototype.reduce
可用来做数组值累加
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4 console.log(array1.reduce(reducer)); // expected output: 10
// 5 + 1 + 2 + 3 + 4 console.log(array1.reduce(reducer, 5)); // expected output: 15
true
的在前面,否则在后面const bifurcateBy = (arr, fn) =>
arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ]
0
个字符是否等于 b
,是的话将该元素放入二维数组的第一个元素中,否则放入第二个元素中指定二维长度(最大)
的二维数组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]]
Array.from(arrayLike[, mapFn[, thisArg]])
方法从一个类似数组或可迭代对象中创建一个新的数组实例;可选参数 mapFn
,让你可以在最后生成的数组上再执行一次 map 方法后再返回
console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]
Array.from([1, 2, 3], x => x + x); // 这个类似 map 方法
// x => x + x代表这是一个函数,只是省略了其他的定义,这是一种Lambda表达式的写法
// 箭头的意思表示从当前数组中取出一个值,然后自加,并将返回的结果添加到新数组中
// [2, 4, 6]
// 创建长度为5的数组,每一项值为 index
的值
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]
// 数组去重合并 Array.from(new Set([1, 2, 3].cocncat([1, 2, 3, 4]))) // [1, 2, 3, 4]
false
的值 (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 ]
// 第二个写法
const filterFalsy = arr => arr.filter(Boolean);
filterFalsy(['', true, {}, false, 'sample', 1, 0]); // [true, {}, 'sample', 1]
对数组的每一项执行 Boolean(item)
,返回值为true
的加入新数组
filter()
方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result); // expected output: Array ["exuberant", "destruction", "present"]
根据给定函数对数组的元素运算得到新数组,然后返回新数组中的各元素的数量
const countBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
// Math.floor 对元素进行 四舍五入 得到新数组 [6, 4, 6], 然后得到统计结果,即 4 有一个,6有2个
countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}
// 传 length 参数代表读取每一项元素的长度, 所以map后的新数组为 [3, 3, 5],统计结果为长度为3的元素有2个,长度为5的元素有1个
countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}
// 按元素首字符统计结果,即 o 开头的有1个,t开头的有2个
countBy(['one', 'two', 'three'], 0); // {o: 1, t: 2}
统计数组中指定值出现的次数
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
countOccurrences([1, 1, 1, 2], 1) // 3
使用递归将多维数组扁平化为一维数组
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]
deepFlatten([1, [2, [3]]]) // [1, 2, 3]
concat
中返回两个数组之间的差异(给定数组a和b,返回一个新数组,仅包含数组a与数组b对比,数组b中没有那些的值)
const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
};
difference([1, 2, 3], [1, 2, 4]); // [3]
difference([1, 2, 3], [1, 2, 3, 4, 5, 6]); // []
根据提供的函数应用于两个数组的每个数组元素后,返回两个数组之间的差异(给定数组a和b以及一个map
中使用的函数,返回一个新数组,仅包含数组a与数组b对比,数组b中没有那些的值)
const differenceBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.map(fn).filter(el => !s.has(el));
};
// Math.floor 四色五入后,是 [2, 1] 与 [2, 3] 对比,后者中没有 1, 所以结果 为 [1]
differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1]
// map 后进行对比的两个数组是 [2, 1] 与 [1], 后者中没有 2, 所以结果为 [2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [2]
使用自定义的比较方法,找出两个数组的差异值
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
// 两个数组在Math.round方法处理后为 [1, 1, 2, 3, 0] 和 [2, 3, 0],第一个数组中的前两项符合对比方法(当在数组val中找不到1的时候,findIndex方法返回-1),所以filter的结果为[1, 1.2]
differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2]
Math.round()
得到最接近的整数,四舍五入
Math.round(1.2) // 1
Math.round(1.5) // 2
Math.round(1.49) // 1
Math.round(-3.5) // 3,因为-3比-3.5大(五入)
findIndex()
方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1
var array1 = [5, 12, 8, 130, 44];
function isLargeNumber(element) { return element > 13; }
console.log(array1.findIndex(isLargeNumber)); // expected output: 3
返回一个从左侧移除n个元素的新数组
const drop = (arr, n = 1) => arr.slice(n);
drop([1, 2, 3]); // [2,3]
drop([1, 2, 3], 2); // [3]
drop([1, 2, 3], 42); // []
返回一个从右边移除n个元素的新数组
const dropRight = (arr, n = 1) => arr.slice(0, -n);
dropRight([1, 2, 3]); // [1,2]
dropRight([1, 2, 3], 2); // [1]
dropRight([1, 2, 3], 42); // []
从数组末尾移除元素,直到传递的函数返回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]
移除数组中的元素,直到传递的函数返回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]
根据提供的间隔数从数组挑选出元素
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
// 每间隔1个挑出来
everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ]
// 每间隔3个挑出来
everyNth([1, 2, 3, 4, 5, 6], 4); // [ 4 ]
返回数组中只出现一次的值(过滤掉出现2次及以上的值)
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]
filterNonUnique([1, 2, 2, 2, 4, 4, 5]); // [1, 5]
indexOf
从头开始查找和使用 lastIndexOf
从尾开始查找,如果获得的索引相同,说明该值在数组中只有一个根据提供的比较器函数过滤数组中的非惟一值(保留唯一值)
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' } ]
every
方法返回false
,此项会被过滤掉返回条件函数
通过filter
过滤后的数组的最后一个值
const findLast = (arr, fn) => arr.filter(fn).pop();
findLast([1, 2, 3, 4], n => n % 2 === 1); // 3
[1, 3]
,其最后一个值为 3返回条件函数通过filter过滤后的数组的最后一个值在原始数组中的索引
const findLastIndex = (arr, fn) =>
arr
.map((val, i) => [i, val])
.filter(([i, val]) => fn(val, i, arr))
.pop()[0];
findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3)
map
函数将数组转换为一个由索引和值组成的二维数组:[1, 2, 3]
=> [[0, 1], [1, 2], [2, 3]]
filter
函数过滤后得到的数组,其实是包含其值在原始数组中的索引值的将多维数组扁平化指定层级(非扁平化到指定层级)
const flatten = (arr, depth = 1) =>
arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 1); // [1, 2, [3, [4, 5], 6], 7, 8]
depth
参数为你想移除的层级数,非移除到指定的层级。例子 2 和 3,清楚的展现了这一情况concat
函数参数可支持数组或者单一值从尾到头开始遍历数组
const forEachRight = (arr, callback) =>
arr
.slice(0)
.reverse()
.forEach(callback);
forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'
slice
获得数组新副本,调用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']}
floor
(向下取整)方法,然后进行分类
检测数组所有元素是否都符合指定条件(提供函数,不提供时,默认使用Boolean)
every()
方法测试数组的所有元素是否都通过了指定函数的测试。var array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold)); // expected output: true