GitHub地址:JavaScript30秒, 从入门到放弃之Array(七)

博客地址:JavaScript30秒, 从入门到放弃之Array(七)

水平有限,欢迎批评指正

without

Filters out the elements of an array, that have one of the specified values.

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

const without = (arr, ...args) => arr.filter(v => !args.includes(v));
复制代码

剔除掉数组中所有存在于所指定的元素们的项。

使用Array.filter()创建一个将所有提供的值排除在外(使用!Array.includes())的数组。

➜  code cat without.js
const without = (arr, ...args) => arr.filter(v => !args.includes(v));console.log(without([2, 1, 2, 3], 1, 2));
➜  code node without.js
[ 3 ]
复制代码

filterincludes结合,把数组arr中所有存在于指定的元素值…args中的项排除在外,很清爽干净。

xProd

Creates a new array out of the two supplied by creating each possible pair from the arrays.

Use Array.reduce(), Array.map() and Array.concat() to produce every possible pair from the elements of the two arrays and save them in an array.

const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
复制代码

创建一个新数组,数组元素由两个数组的元素交叉组合而成。

使用Array.reduce()Array.map()Array.concat()来创建由两个数组元素拼接而成的所有可能对并将它们存在一个数组中的数组。

➜  code cat xProd.js
const xProd = (a, b) => a.reduce((acc, val) => acc.concat(b.map(v => [val, v])), []);console.log(xProd([1, 2], ['a', 'b']));➜  code node xProd.js
[ [ 1, 'a' ], [ 1, 'b' ], [ 2, 'a' ], [ 2, 'b' ] ]
复制代码

reduce初始值acc是一个空数组[],随着遍历的进行accconcat生成的元素组合对的数组。组合对就是由b.map(v => [val, v]生成的。也就是reduce遍历一次时,数组a的一个元素分别和数组b的所有元素分别组成一对。

zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from()with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

const zip = (...arrays) => {const maxLength = Math.max(...arrays.map(x => x.length));return Array.from({ length: maxLength }).map((_, i) => {return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);});
};
复制代码

创建一个数组,数组元素由指定的多个数组根据位置对应分组而成的数组构成。例如,多个数组的第一个元素组成一个新数组,第二个元素组成一个新数组,依次类推。最终把所有分类号的数组存到一个数组中。

先使用Math.max.apply()来计算出最终成组的长度,然后使用该长度结合Array.from()map去遍历创建该数组的所有分组子数组。如果其中任意一个数组在对应位置上元素不存在(如长度为2的数组试图获取第3个元素)则undefined将被使用。

➜  code cat zip.js
const zip = (...arrays) => {const maxLength = Math.max(...arrays.map(x => x.length));return Array.from({length: maxLength}).map((_, i) => Array.from({length: arrays.length}, (_, k) => arrays[k][i]));
};console.log(zip(['a', 'b'], [1, 2], [true, false]));
console.log(zip(['a'], [1, 2], [true, false]));➜  code node zip.js
[ [ 'a', 1, true ], [ 'b', 2, false ] ]
[ [ 'a', 1, true ], [ undefined, 2, false ] ]
复制代码
const maxLength = Math.max(...arrays.map(x => x.length));
复制代码

这是最终分成maxLength组,比如一个数组含有100个元素,另一个数组含有1个元素,最终要分成100组,所以需要用Math.max()去获取所有数组中长度最长的那个。

return Array.from({length: maxLength}).map((_, i) => Array.from({length: arrays.length}).map((_, k) => arrays[k][i])
);
复制代码

使用Array.from结合length生成长度为maxLength的数组这没啥说的了,重点是map后的方法,map的每一个数组里包含多少个元素才可以呢?稍微想一下就知道,应该是arrays的个数,因为每一个数组都要拿一个出来组装。所以这里又用了一个Array.from配上length: arrays.length来定一个数组里包含的元素数量。那么这些元素由什么组成呢?这里还是要配合一个(_, k) => arrays[k][i])方法去取arrays的元素。获取的是对应每一个数组的第i个元素。

zipObject

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

const zipObject = (props, values) =>props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
复制代码

提供一个有效的属性标识符的数组和一个含值数组,返回一个把属性和值拼合的对象。即有效的属性标识符数组的第一项为键,含值数组的第一项为值,依次类推。

由于一个对象值可以为undefined而键不能为undefined,所以只有有效的属性标识符数组能用来决定了对象的组成结构。因而使用Array.reduce()对该数组进行相关操作。

➜  code cat zipObject.js
const zipObject = (props, values) => props.reduce((acc, val, i) => ((acc[val] = values[i]), acc), {});console.log(zipObject(['a', 'b', 'c'], [1, 2]));
console.log(zipObject(['a', 'b'], [1, 2, 3]));➜  code node zipObject.js
{ a: 1, b: 2, c: undefined }
{ a: 1, b: 2 }
复制代码
(obj[prop] = values[index]), obj)
复制代码

JavaScript的逗号运算符是指按照顺序执行表达式,最终返回最后一个表达式的运行结果。对于这个例子来说,就是先创造一个键值对,最后返回该对象。换一般的写法就是如下:

obj[prop] = values[index];
return obj;
复制代码

这点弄通了就好理解了。

实际上就是以props数组为基准,对其运用reduce方法去遍历数组,初始值obj是一个空对象{},遍历过程以props数组的值prop为键,props数组当前索引index为索引去取values数组的项为值组装成对象并返回。

由于对象的键不能为undefined,因此,如果数组props的长度比数组values小,那么values多出来的那些项就不管了。如果相反,那么该对象相应键的值为undefined

zipWith

Creates an array of elements, grouped based on the position in the original arrays and using function as the last value to specify how grouped values should be combined.

Check if the last argument provided in a function. Use Math.max() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found. The function is invoked with the elements of each group (...group).

const zipWith = (...arrays) => {const length = arrays.length;let fn = length > 1 ? arrays[length - 1] : undefined;fn = typeof fn == 'function' ? (arrays.pop(), fn) : undefined;const maxLength = Math.max(...arrays.map(x => x.length));const result = Array.from({ length: maxLength }).map((_, i) => {return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);});return fn ? result.map(arr => fn(...arr)) : result;
};
复制代码

创建一个数组,数组元素由指定的多个数组根据位置对应分组而成的数组构成,然后分组后的数组元素应用指定方法进行结合。

➜  code cat zipWith.js
const zipWith = (...arrays) => {const length = arrays.length;let fn = length > 1 ? arrays[length - 1] : undefined;fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined;const maxLength = Math.max(...arrays.map(x => x.length));const result = Array.from({length: maxLength}).map((_, i) => {return Array.from({length: arrays.length}, (_, k) => arrays[k][i]);});return fn ? result.map(arr => fn(...arr)) : result;
};console.log(zipWith([1, 2], [10, 20], [100, 200], (a, b, c) => a + b + c));
console.log(zipWith([1, 2, 3],[10, 20],[100, 200],(a, b, c) => (a != null ? a : 'a') + (b != null ? b : 'b') + (c != null ? c : 'c')
));➜  code node zipWith.js
[ 111, 222 ]
[ 111, 222, '3bc' ]
复制代码
const length = arrays.length;
let fn = length > 1 ? arrays[length - 1] : undefined;
fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined;
复制代码

首先这里把参数长度arrays.length存到length里,然后根据参数长度length判断参数里是否指定了某个方法。如果length小于等于1,则没有传入指定方法,因而fn = undefined;否则,认为参数的最后一个arrays[length - 1]传入了方法。

接下来还得判断fn是不是一个function,如果是,arrays.pop()把方法剔除,只留数组,然后返回fn赋值给fn;否则把undefined赋值给fn

其实我觉得这里和前面的写重复了,我觉得fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined改成下面更好:

if (typeof fn === 'function') {arrays.pop();
}
复制代码

这样就避免了fn的重复赋值了。因为fn = typeof fn === 'function' ? (arrays.pop(), fn) : undefined这一行的作用就是为了把方法pop出去而已,没必要再重新赋值。

const maxLength = Math.max(...arrays.map(x => x.length));
复制代码

这一行计算出最终返回数组的长度,这点易证,不展开。

const result = Array.from({ length: maxLength }).map((_, i) => {return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
});
复制代码

这里其实和前面的zip方法是一样的,到现在为止返回的result是和zip的结果是一样的。

return fn ? result.map(arr => fn(...arr)) : result;
复制代码

然后判断fn是不是非undefined,如果是不用处理直接返回result,否则对result数组所有元素调用fn方法并返回结果。需要注意的是参数…arr是需要展开的,参数不是单个的数组元素,而是数组的所有元素。

到目前为止,我已经把数组的都过了一遍了,不过因为这个 30 seconds of code一直在开发当中,所以在我翻译过程中,数组的项又增加了很多个,下面部分为新增的项。

all

Returns true if all elements in a collection are truthy, false otherwise.

Use Array.every(Boolean) to test if all elements in the collection are truthy.

const all = arr => arr.every(Boolean);
复制代码

如果数组所有元素为真,返回true,否则返回false

使用Array.every(Boolean) 来检测数组所有元素是否都为真。

➜  code cat all.js
const all = arr => arr.every(Boolean);console.log(all([1, 2, 3]));➜  code node all.js
true
复制代码

这其实就是Array.every()函数能做的事情。参数为Boolean就是判断是不是数组所有元素布尔为都为真。

allBy

Returns true if the provided predicate function returns true for all elements in a collection, false otherwise.

Use Array.every() to test if all elements in the collection return true based on fn.

const allBy = (arr, fn) => arr.every(fn);
复制代码

如果数组所有元素应用了指定的断言方法都为真,那么返回true,否则返回false

使用Array.every()结合fn来检测数组所有元素调用fn后布尔值是否都为真。

➜  code cat allBy.js
const allBy = (arr, fn) => arr.every(fn);console.log(allBy([4, 2, 3], x => x > 1));➜  code node allBy.js
true
复制代码

all多了一个fn方法而已,只需要把every的参数换成fn就行,这没啥可说的。

any

Returns true if at least one element in a collection is truthy, false otherwise.

Use Array.some(Boolean) to test if any elements in the collection are truthy.

const any = arr => arr.some(Boolean);
复制代码

如果一个数组中至少有一个元素布尔值为真,返回true,否则返回false

使用Array.some(Boolean)来检测数组中是否有一个元素布尔值为真。

➜  code cat any.js
const any = arr => arr.some(Boolean);console.log(any([0, 0, 1, 0]));➜  code node any.js
true
复制代码

这就是Array.some()可以做的事情,没啥可说。

anyBy

Returns true if the provided predicate function returns true for at least one element in a collection, false otherwise.

Use Array.some() to test if any elements in the collection return true based on fn.

const anyBy = (arr, fn) => arr.some(fn);
复制代码

如果对一个数组的元素运用指定的断言方法后至少有一个结果布尔值为真,返回true,否则返回false

使用Array.some()结合fn检测一个数组中调用指定断言方法后至少有一个结果布尔值为真。

➜  code cat anyBy.js
const anyBy = (arr, fn) => arr.some(fn);console.log(anyBy([0, 1, 2, 0], x => x >= 2));➜  code node anyBy.js
true
复制代码

any多了一个fn方法而已,只需要把some的参数换成fn就行,这没啥可说的。

bifurcate

Splits values into two groups. If an element in filter is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group.

Use Array.reduce() and Array.push() to add elements to groups, based on filter.

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

把一个数组分裂成两组。如果一个元素在filter中对应值是truthy,那么相应位置的被分裂元素归属于第一个组,否则归属于第二个组。

使用Array.reduce()Array.push()filter的基础上把待分裂的元素添加到相应的组中。

➜  code cat bifurcate.js
const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);console.log(bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]));➜  code node bifurcate.js
[ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]
复制代码

reduce初始值acc是一个含有两个空数组的二维数组[[], []],遍历过程中去判断对应索引filter的值filter[i]是否为truthy,若真,则把当前索引对应元素val加到acc[0]中;否则加到acc[1]中。遍历结束,分组完成。

bifurcateBy

Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group.

Use Array.reduce() and Array.push() to add elements to groups, based on the value returned by fn for each element.

const bifurcateBy = (arr, fn) =>arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
复制代码

根据提供的断言方法将一个数组分裂成两组。如果断言结果为truthy,该元素将被分配到第一组,否则分配在第二组。

使用Array.reduce()Array.push()在断言方法fn的基础上将待分裂的元素添加到相应的组中。

➜  code cat bifurcateBy.js
const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);console.log(bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'));
➜  code node bifurcateBy.js
[ [ 'beep', 'boop', 'bar' ], [ 'foo' ] ]
复制代码

bifurcate相比不同的地方是:

(acc[fn(val, i) ? 0 : 1].push(val), acc)
复制代码

这里是对数组的元素val调用指定方法,而bifurcate是对应位置filter[i]的直接结果。其余都是一样的。这也很好理解了。

JavaScript30秒, 从入门到放弃之Array(七)相关推荐

  1. JavaScript30秒, 从入门到放弃之Array(三)

    原文链接:JavaScript30秒, 从入门到放弃之Array(三) 水平有限,欢迎批评指正 flattenDepth Flattens an array up to the specified d ...

  2. JavaScript从入门到放弃 -(五)函数进阶(高级用法)

    目录 1. 函数的定义和调用 1.1 函数定义的3种方式 1.2 函数调用方式(常见的6种) 1.2.1 普通函数的调用 1.2.2 对象中的函数调用 1.2.3 构造函数的调用 1.2.4 DOM元 ...

  3. iOS即时通讯,从入门到“放弃”?

    image 前言 本文会用实例的方式,将iOS各种IM的方案都简单的实现一遍.并且提供一些选型.实现细节以及优化的建议. 注:文中的所有的代码示例,在github中都有demo: iOS即时通讯,从入 ...

  4. iOS即时通讯从入门到“放弃”?

    前言 本文会用实例的方式,将iOS各种IM的方案都简单的实现一遍.并且提供一些选型.实现细节以及优化的建议. 注:文中的所有的代码示例,在github中都有demo: iOS即时通讯,从入门到&quo ...

  5. GPS从入门到放弃(八) --- GPS卫星速度解算

    GPS从入门到放弃(八) - GPS卫星速度解算 在阅读这一篇强烈建议先阅读GPS卫星位置解算. 为了计算卫星速度,需要对卫星的位置求导. 计算各参变量对时间的导数如下: M˙k=n\dot{M}_k ...

  6. JavaScript从入门到放弃到精通

    JavaScript从入门到放弃 1.什么是JS 是一种流行的脚本语言, Java和JS没有什么关系 1.2环境 1.3调试 运行html 控制台调试 console.log()变量打印输出 断点 2 ...

  7. Hive从入门到放弃——HiveQL表级别DDL设计的艺术性(五)

    HiveQL数据库中的表DDL操作   博客Hive从入门到放弃--HiveQL数据库级别DDL设计的艺术性(四)聊完了数据库的基本操作,我们再来聊聊Hive内表的操作. 创建表   官方推荐建表的结 ...

  8. GPS从入门到放弃(七) --- GPS卫星位置解算

    GPS从入门到放弃(七) - GPS卫星位置解算 上一篇讲了开普勒轨道参数,根据这些参数就可以确定卫星的位置,这一篇我们来实际计算一下. WGS-84基本参数 首先给出几个WGS-84坐标系中的基本参 ...

  9. AI从入门到放弃2:CNN的导火索,用MLP做图像分类识别?

    来源 | 腾讯知乎专栏 作者 | AIoys(腾讯员工,后台工程师) 项目文档和代码在此:github项目地址: https://github.com/zsysuper/AI_Notes ▌一.前言 ...

  10. 30分钟git命令入门到放弃

    30分钟git命令入门到放弃 Helkyle・ 15 小时前 172 | 暂无评论 这是一篇给像我这样的新手或者是熟悉图形工具的老鸟看的.仅作为快速入门的教程. learn-git git 现在的火爆 ...

最新文章

  1. Kali Linux常用服务配置教程DHCP服务原理
  2. 【Groovy】Groovy 扩展方法 ( 静态扩展方法配置 | 扩展方法示例 | 编译静态扩展类 | 打包静态扩展类字节码到 jar 包中 | 测试使用 Thread 静态扩展类 )
  3. kafka分区(partition)和和分组(group)
  4. java 700c corsa_JAVA CORSA休闲车,缔造“城市 生活 元素”
  5. 1.1 Java注解(Annotation)简介
  6. 计算机ppt制作教案,全国计算机一级B考试基础篇制作人徐守威PPT教案学习.pptx
  7. 关于c++输出中的endl
  8. ARM中 __IO的作用解析
  9. 华为软件研发面试题1
  10. 如何理解typedef void
  11. Android开发中常见的内存泄露案例以及解决方法总结
  12. mac地址查 计算机名字,怎么看mac地址-教你通过MAC地址查询设备的厂商名称
  13. 音频噪声抑制_音频编辑入门指南:基本噪声消除
  14. 《学习笔记》在AngularJS视图中实现指令
  15. 微型计算机煎蛋网,煎蛋网 No.4950004
  16. 如何将Excel的单元格设置成下拉选项?-excel设置下拉菜单
  17. 轻松学会分布式事务算法
  18. 计算机控制技术第二章,微型计算机控制技术 赖寿宏版 课件 第二章.ppt
  19. DataGear 自定义数据可视化图表
  20. 创业公司第三方服务精选(移动互联网版)

热门文章

  1. jsp注释%-- -- % 和 !-- -- 的区别
  2. html/css静态网页制作
  3. 北漂周记--第5记--拼命编程
  4. 转电感和磁珠两兄弟的差别
  5. SQL server中如何使用return,break和continue
  6. VS2010/MFC编程入门之前言
  7. Boring Old Menu Bar for Mac(Big Sur菜单栏优化工具)
  8. DoYourData AppUninser Mac版(Mac应用卸载工具)
  9. mysql主从延迟设置
  10. k8s-kubectl进程源码分析