[译]【30秒一个知识点】Array(三)

时间:2022-06-21
本文章向大家介绍[译]【30秒一个知识点】Array(三),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本系列翻译自开源项目 30-seconds-of-code 这是一个非常优秀的系列,不是说真的三十秒就能理解,也需要你认真的思考,其中有一些点非常精妙,很值得一读。 本文在我的github同步更新,点击文章末尾阅读全文你可以看到当前翻译的全部系列。

everyNth

返回数组中所有下标是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 ]

filterFalsy

把数组中的 虚值过滤掉。

使用 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]

filterNonUnique

过滤调数组中重复的值。

使用 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]

filterNonUniqueBy

基于给定的比较器函数,过滤掉数组中重复的元素。

使用 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' } ]

findLast

返回所提供函数返回 真值的最后一个元素。

使用 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

findLastIndex

返回所提供函数返回 真值的最后一个元素的索引。

使用 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)

flatten

根据指定的深度展平一个数组。

使用递归,每层递归 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]

forEachRight

对数组中的每个元素执行一次所提供的函数,从数组的最后一个元素开始。

使用 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'

groupBy

基于给定的函数将数组分组。

使用 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

indexOfAll

返回一个数组中所有 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); // []

initial

返回数组中除最后一个元素外的所有元素。

使用 arr.slice(0,-1) 返回数组中除最后一个元素外的所有元素。

const initial = arr => arr.slice(0, -1);

示例

initial([1, 2, 3]); // [1,2]

initialize2DArray

根据给定的宽、高和值初始化一个二维数组。

使用 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() 可以通过以下方式来创建数组对象:

  • 伪数组对象(拥有一个 length 属性和若干索引属性的任意对象) 例: Array.from({length:10})
  • 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)

示例

initialize2DArray(2, 2, 0); // [[0,0], [0,0]]

initializeArrayWithRange

初始化一个数组,该数组包括从 startend 指定范围的数字,并且包括共同的公差 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]

initializeArrayWithRangeRight

初始化一个数组,该数组包括从 startend 指定范围的数字(反向的),并且包括共同的公差 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]

initializeArrayWithValues

初始化一个数组,并且使用指定的值填充它。

使用 Array(n) 创建一个期望长度的数组,使用 fill(v) 用期望的值填充数组。

你可以省略参数 val 使用默认值 0

const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);

示例

initializeArrayWithValues(5, 2); // [2, 2, 2, 2, 2]

initializeNDArray

使用给定的值创建一个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]]]