扁平化

数组的扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。

举个例子,假设有个名为 flatten 的函数可以做到数组扁平化,效果就会如下:

var arr = [1, [2, [3, 4]]];
console.log(flatten(arr)) // [1, 2, 3, 4]

递归

如果还是一个数组,就递归调用该方法:

var arr = [1, [2, [3, 4]]]; function flatten(arr) { var result = []; for (var i = 0, len = arr.length; i < len; i++) { if (Array.isArray(arr[i])) { result = result.concat(flatten(arr[i])) } else { result.push(arr[i]) } } return result; } console.log(flatten(arr))

toString

如果数组的元素都是数字,那么我们可以考虑使用 toString 方法,因为:

[1, [2, [3, 4]]].toString() // "1,2,3,4"复制代码

调用 toString 方法,返回了一个逗号分隔的扁平的字符串,这时候我们再 split,然后转成数字不就可以实现扁平化了吗?

// 方法2
var arr = [1, [2, [3, 4]]]; function flatten(arr) {
return arr.toString().split(',').map(function(item){
return +item
})
} console.log(flatten(arr))复制代码

然而这种方法使用的场景却非常有限,如果数组是 [1, '1', 2, '2'] 的话,这种方法就会产生错误的结果。

reduce

既然是对数组进行处理,最终返回一个值,我们就可以考虑使用 reduce 来简化代码:

// 方法3
var arr = [1, [2, [3, 4]]]; function flatten(arr) {
return arr.reduce(function(prev, next){
return prev.concat(Array.isArray(next) ? flatten(next) : next)
}, [])
} console.log(flatten(arr))

S6 增加了扩展运算符,用于取出参数对象的所有可遍历属性,拷贝到当前对象之中:

var arr = [1, [2, [3, 4]]];
console.log([].concat(...arr)); // [1, 2, [3, 4]]复制代码

我们用这种方法只可以扁平一层,但是顺着这个方法一直思考,我们可以写出这样的方法:

// 方法4
var arr = [1, [2, [3, 4]]]; function flatten(arr) { while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
} return arr;
} console.log(flatten(arr))

undercore

那么如何写一个抽象的扁平函数,来方便我们的开发呢,所有又到了我们抄袭 underscore 的时候了~

在这里直接给出源码和注释,但是要注意,这里的 flatten 函数并不是最终的 _.flatten,为了方便多个 API 进行调用,这里对扁平进行了更多的配置。

/**
* 数组扁平化
* @param {Array} input 要处理的数组
* @param {boolean} shallow 是否只扁平一层
* @param {boolean} strict 是否严格处理元素,下面有解释
* @param {Array} output 这是为了方便递归而传递的参数
* 源码地址:https://github.com/jashkenas/underscore/blob/master/underscore.js#L528
*/
function flatten(input, shallow, strict, output) { // 递归使用的时候会用到output
output = output || [];
var idx = output.length; for (var i = 0, len = input.length; i < len; i++) { var value = input[i];
// 如果是数组,就进行处理
if (Array.isArray(value)) {
// 如果是只扁平一层,遍历该数组,依此填入 output
if (shallow) {
var j = 0, len = value.length;
while (j < len) output[idx++] = value[j++];
}
// 如果是全部扁平就递归,传入已经处理的 output,递归中接着处理 output
else {
flatten(value, shallow, strict, output);
idx = output.length;
}
}
// 不是数组,根据 strict 的值判断是跳过不处理还是放入 output
else if (!strict){
output[idx++] = value;
}
} return output; }

解释下 strict,在代码里我们可以看出,当遍历数组元素时,如果元素不是数组,就会对 strict 取反的结果进行判断,如果设置 strict 为 true,就会跳过不进行任何处理,这意味着可以过滤非数组的元素,举个例子:

var arr = [1, 2, [3, 4]];
console.log(flatten(arr, true, true)); // [3, 4]复制代码

那么设置 strict 到底有什么用呢?不急,我们先看下 shallow 和 strct 各种值对应的结果:

  • shallow true + strict false :正常扁平一层
  • shallow false + strict false :正常扁平所有层
  • shallow true + strict true :去掉非数组元素
  • shallow false + strict true : 返回一个[]

_.flatten

首先就是 _.flatten:

_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
};复制代码

在正常的扁平中,我们并不需要去掉非数组元素。

_.union

接下来是 _.union:

该函数传入多个数组,然后返回传入的数组的并集,

举个例子:

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]复制代码

如果传入的参数并不是数组,就会将该参数跳过:

_.union([1, 2, 3], [101, 2, 1, 10], 4, 5);
=> [1, 2, 3, 101, 10]复制代码

为了实现这个效果,我们可以将传入的所有数组扁平化,然后去重,因为只能传入数组,这时候我们直接设置 strict 为 true,就可以跳过传入的非数组的元素。

// 关于 unique 可以查看《JavaScript专题之数组去重》[](https://github.com/mqyqingfeng/Blog/issues/27)
function unique(array) {
return Array.from(new Set(array));
} _.union = function() {
return unique(flatten(arguments, true, true));
}

_.difference

是不是感觉折腾 strict 有点用处了,我们再看一个 _.difference:

语法为:

_.difference(array, *others)

效果是取出来自 array 数组,并且不存在于多个 other 数组的元素。跟 _.union 一样,都会排除掉不是数组的元素。

举个例子:

_.difference([1, 2, 3, 4, 5], [5, 2, 10], [4], 3);
=> [1, 3]复制代码

实现方法也很简单,扁平 others 的数组,筛选出 array 中不在扁平化数组中的值:

function difference(array, ...rest) {

    rest = flatten(rest, true, true);

    return array.filter(function(item){
return rest.indexOf(item) === -1;
})
}

javascrip的数组扁平化的更多相关文章

  1. JS: 数组扁平化

    数组扁平化 什么是数组扁平化? 数组扁平化就是将一个多层嵌套的数组 (Arrary) 转化为只有一层. // 多层嵌套 [1, 2, [3, 4]] // 一层 [1, 2, 3, 4] 递归实现 思 ...

  2. js技巧-使用reduce实现更简洁的数组对象去重和数组扁平化

    Array.prototype.reduce()方法介绍: 感性认识reduce累加器: const arr = [1, 2, 3, 4]; const reducer = (accumulator, ...

  3. JS数组专题1️⃣ ➖ 数组扁平化

    一.什么是数组扁平化 扁平化,顾名思义就是减少复杂性装饰,使其事物本身更简洁.简单,突出主题. 数组扁平化,对着上面意思套也知道了,就是将一个复杂的嵌套多层的数组,一层一层的转化为层级较少或者只有一层 ...

  4. js多维数组扁平化

    数组扁平化,就是将多维数组碾平为一维数组,方便使用. 一:例如,一个二维数组 var arr = ['a', ['b', 2], ['c', 3, 'x']],将其扁平化: 1.  通过 apply ...

  5. js中数组扁平化处理

  6. js实现数组扁平化

    数组扁平化的方式 什么是数组扁平化? 数组扁平化:指将一个多维数组转化为一个一维数组. 例:将下面数组扁平化处理. const arr = [1, [2, 3, [4, 5]]] // ---> ...

  7. JavaScript数组常用方法解析和深层次js数组扁平化

    前言 数组作为在开发中常用的集合,除了for循环遍历以外,还有很多内置对象的方法,包括map,以及数组筛选元素filter等. 注:文章结尾处附深层次数组扁平化方法操作. 作为引用数据类型的一种,在处 ...

  8. js数组扁平化

    看到一个有趣的题目: var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; 一个多维 ...

  9. JS数组扁平化(flat)

    需求:多维数组=>一维数组 let ary = [1, [2, [3, [4, 5]]], 6]; let str = JSON.stringify(ary); 第0种处理:直接的调用 arr_ ...

随机推荐

  1. SpringBoot 集成mongodb(1)单数据源配置

    新项目要用到mongodb,于是在个人电脑上的虚拟环境linux上安装了下mongodb,练习熟悉下. 1.虚拟机上启动mongodb. 首先查看虚拟机ip地址,忘了哈~~ 命令行>ifconf ...

  2. dependencies 和 starter

    以 spring-cloud-alibaba-dependencies-1.5.0.RELEASE 为例: <dependency> <groupId>com.alibaba. ...

  3. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_08 转换流_6_练习_转换文件编码

  4. Week2 - 669. Trim a Binary Search Tree & 617. Merge Two Binary Trees

    Week2 - 669. Trim a Binary Search Tree & 617. Merge Two Binary Trees 669.Trim a Binary Search Tr ...

  5. 《上瘾 - 让用户养成使用习惯的四大产品逻辑》 - Nir Eyal, Ryan Hoover

    <上瘾 - 让用户养成使用习惯的四大产品逻辑> - Nir Eyal, Ryan Hoover 前言 1.所谓的消费升级,就是个人愿意付出更高的成本购买与自我价值相匹配的产品.购买即是一种 ...

  6. 14 (H5*) JS第4天 函数、作用域、预解析

    目录 1:函数的其他定义 2:函数作为参数 3:函数作为返回值 4:作用域 5:作用域链 6:预解析 7:预解析分段 复习 <script> /* * 复习: * 函数:把一些重复的代码封 ...

  7. 2019寒假作业三:PTA7-1抓老鼠啊~亏了还是赚了

    - 抓老鼠啊~亏了还是赚了? ( 分) 某地老鼠成灾,现悬赏抓老鼠,每抓到一只奖励10元,于是开始跟老鼠斗智斗勇:每天在墙角可选择以下三个操作:放置一个带有一块奶酪的捕鼠夹(T),或者放置一块奶酪(C ...

  8. linux中cut命令

    cut命令 cut常用参数 cut命令用来显示行中的指定部分,删除文件中指定字段. 说明:该命令有两项功能,其一是用来显示文件的内容,它依次读取由参数file所指明的文件,将它们的内容输出到标准输出上 ...

  9. MySQL学习笔记(上)

    在进行SQL注入原理的剖析的时候,对MySQL数据库掌握薄弱,参照菜鸟教程的MySQL教程速刷一遍MySQL 关于MySQL MySQL是最流行的关系型数据库管理系统,在WEB方面MySQL是最好的R ...

  10. 20171110面试笔记 服务器端程序员+C/C++开发

    socket 模型: https://www.cnblogs.com/nsnow/archive/2011/05/03/2036017.html http://blog.csdn.net/normal ...