本系列翻译自开源项目 30-seconds-of-code 这是一个非常优秀的系列,不是说真的三十秒就能理解,也需要你认真的思考,其中有一些点非常精妙,很值得一读。 本文在我的github同步更新,点击文章末尾阅读全文你可以看到当前翻译的全部系列。
返回数组中所有下标是n的倍数的元素。
使用 Array.prototype.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 ]
把数组中的 虚值
过滤掉。
使用 Array.prototype.filter()
创建一个只包含 真值
的新数组。
const filterFalsy = arr => arr.filter(Boolean);
falsy
(虚值)是在Boolean
上下文中已认定可转换为‘假‘的值。例如:false,0,"",null,undefined 和 NaN 。Truthy
(真值)指的是在 布尔值 上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为falsy
。
示例
filterFalsy(['', true, {}, false, 'sample', 1, 0]); // [true, {}, 'sample', 1]
过滤调数组中重复的值。
使用 Array.prototype.filter()
创建一个只包含唯一值的数组。
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 filter 不会改变原数组,它返回过滤后的新数组。
示例
filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]
基于给定的比较器函数,过滤掉数组中重复的元素。
使用 Array.prototype.filter()
和 Array.prototype.every()
创建一个新数组,该数组只包含唯一值,基于给定的比较器函数 fn
。
比较器函数接收四个参数:正在被比较的两个元素和他们的索引。
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' } ]
返回所提供函数返回 真值
的最后一个元素。
使用 Array.prototype.filter()
将调用 fn
后返回 虚值
的元素过滤掉, 然后调用 Array.prototype.pop()
来获取最后一个元素。
const findLast = (arr, fn) => arr.filter(fn).pop();
示例
findLast([1, 2, 3, 4], n => n % 2 === 1); // 3
返回所提供函数返回 真值
的最后一个元素的索引。
使用 Array.prototype.map()
将每个元素映射到具有其索引和值的数组。使用 Array.prototype.filter()
将调用 fn
后返回 虚值
的元素过滤掉, 然后调用 Array.prototype.pop()
来获取最后一个元素的索引。
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)
根据指定的深度展平一个数组。
使用递归,每层递归 depth
递减1。使用 Array.prototype.reduce()
和 Array.prototype.concat()
来合并数组或者元素。基本情况下,当 depth
等于1时停止递归。忽略第二个参数的情况下, depth
默认为1(单层展开)。
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]
对数组中的每个元素执行一次所提供的函数,从数组的最后一个元素开始。
使用 Array.prototype.slice(0)
克隆给定的数组,并使用 Array.prototype.reverse()
将它反转,然后使用 Array.prototype.forEach()
遍历反转后的数组。
const forEachRight = (arr, callback) => arr .slice(0) .reverse() .forEach(callback);
示例
forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'
基于给定的函数将数组分组。
使用 Array.prototype.map()
将组数中的值映射到一个函数或者属性名。
使用 Array.prototype.reduce()
创建一个对象,其中的键由映射的结果生成。
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']}
返回列表的头部
使用 arr[0]
返回传递数组的第一个元素。
const head = arr => arr[0];
示例
head([1, 2, 3]); // 1
返回一个数组中所有 val
的索引。如果 val
不存在,返回 []
。
使用 Array.prototype.reduce()
遍历元素,将匹配的元素索引存储下来,返回索引数组。
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
示例
indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]indexOfAll([1, 2, 3], 4); // []
返回数组中除最后一个元素外的所有元素。
使用 arr.slice(0,-1)
返回数组中除最后一个元素外的所有元素。
const initial = arr => arr.slice(0, -1);
示例
initial([1, 2, 3]); // [1,2]
根据给定的宽、高和值初始化一个二维数组。
使用 Array.prototype.map()
生成 h
行,其中每一行都是大小为 w
的新数组,并用值初始化。如果没有提供该值,则默认为 null
。
const initialize2DArray = (w, h, val = null) => Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
Array.from() 可以通过以下方式来创建数组对象:
Array.from({length:10})
示例
initialize2DArray(2, 2, 0); // [[0,0], [0,0]]
初始化一个数组,该数组包括从 start
到 end
指定范围的数字,并且包括共同的公差 step
。
使用 Array.from()
创建一个所需长度 (end-start+1)/step
的数组,然后指定一个匹配函数将指定范围内的所需值填充到数组中。
你可以省略 start
使用默认值 0
。你可以省略 step
使用默认值 1
。
const initializeArrayWithRange = (end, start = 0, step = 1) => Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
Array.from()
方法有一个可选参数 mapFn,让你可以在最后生成的数组上再执行一次map
方法后再返回。也就是说Array.from(obj,mapFn,thisArg)
就相当于Array.from(obj).map(mapFn,thisArg)
。
示例
initializeArrayWithRange(5); // [0,1,2,3,4,5]initializeArrayWithRange(7, 3); // [3,4,5,6,7]initializeArrayWithRange(9, 0, 2); // [0,2,4,6,8]
初始化一个数组,该数组包括从 start
到 end
指定范围的数字(反向的),并且包括共同的公差 step
。
使用 Array.from(Math.ceil((end+1-start)/step))
创建一个期望长度的数组(为了兼容结束,元素的数量等同于 (end-start)/step
或 (end+1-start)/step
),使用 Array.prototype.map()
来填充期望范围内的值。
你可以省略 start
使用默认值 0
。你可以省略 step
使用默认值 1
。
const initializeArrayWithRangeRight = (end, start = 0, step = 1) => Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( (v, i, arr) => (arr.length - i - 1) * step + start );
示例
initializeArrayWithRangeRight(5); // [5,4,3,2,1,0]initializeArrayWithRangeRight(7, 3); // [7,6,5,4,3]initializeArrayWithRangeRight(9, 0, 2); // [8,6,4,2,0]
初始化一个数组,并且使用指定的值填充它。
使用 Array(n)
创建一个期望长度的数组,使用 fill(v)
用期望的值填充数组。
你可以省略参数 val
使用默认值 0
。
const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
示例
initializeArrayWithValues(5, 2); // [2, 2, 2, 2, 2]
使用给定的值创建一个n维数组。
使用递归。使用 Array.prototype.map()
来生成行,这些行每一个都是使用 initializeNDArray
初始化的新数组。
const initializeNDArray = (val, ...args) => args.length === 0 ? val : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
示例
initializeNDArray(1, 3); // [1,1,1]initializeNDArray(5, 2, 2, 2); // [[[5,5],[5,5]],[[5,5],[5,5]]]