除了flat可以让数组扁平化之外还有其他方法进行扁平化吗?将多维数组扁平化并去重,最后得到一个升序不重复的数组

本文探讨如何在JavaScript中实现多维数组的扁平化和去重,不依赖于Array.prototype.flat()方法。通过使用concat()、reduce()以及自定义函数的方式详细讲解了两种扁平化方法,并展示了如何结合Set和排序得到一个升序且无重复的一维数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JS 编写一个程序将数组(多维数组)扁平化后进行数组去重,最终得到一个升序且不重复的一维数组。

var arr = [[12,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,[14]]]]]

这个题有一种非常简洁的方法,一行搞定。
这里直接用 .from() , .flat(),.sort()三个API加上Set,这样非常的简明。这里

 var arr = [[12, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]]];
 console.log(Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>a-b));

在这里我们主要讨论的是:是否可以不用flat这个API而对数组进行扁平化呢?

答:当然能了!

方法一:使用 concat()

concat() 方法用于合并多个数组,是一个纯函数,因为此方法不会改变原数组,而是返回一个新数组。

先来看一个简单的例子吧:

    var arr1 = [1,2,3];
    var arr2 = [4,5];
    console.log(arr1.concat(arr2));  // [1, 2, 3, 4, 5]

由上面例子可以看出,concat()是可以合并多个数组的。难么,如果是一个多维数组呢?还可以合并吗?当然能了呀,但是右下图可见此数组最后一个元素是一个数组,那么今天的重点来了!
在这里插入图片描述
知道了concat是干什么的之后,就要考虑用concat 怎样才能实现扁平化呢?
主要思路如下:

  1. 首先封装一个扁平化的函数 function flatten(){ };
  2. 在函数里遍历整个数组
  3. 在flatten()函数里定义一个新数组用于接受扁平化的新数组
  4. 在flatten()函数里还需要定义一个函数去判断遍历元素是否是一个数组,若是遍历元素1一个数组,则需要在此调用flatten(),若判断遍历元素1里面还有数组,那么继续调用flatten()…知道没有数组位置,这个过程就是所谓的递归;若遍历元素1是一个正常的字符串则将次元素存到nArr这个新数组里面。
    var arr = [[12, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]]];
    // 封装flatten()函数
    function flatten(array) {
        // 创建一个新数组
        let nArr = [];
        // 定义函数判断是否是数组
        function isArr(isarr) {
            // {}.toString.call(isarr)调用了根元素的
            return {}.toString.call(isarr) == '[object Array]';
        }
        for (var i = 0; i < array.length; i++) {
            if (isArr(array[i])) {
                nArr = nArr.concat(flatten(array[i]))
            } else {
                nArr.push(array[i])
            }
        }
    }
    console.log(flatten(arr)); // [12, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14]
    console.log(Array.from(new Set(flatten(arr).sort((a, b) => { return a - b }))));
    // [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]
    
注: {}.toString.call( ) 检测数据的原型
 	“根”原型(Object.prototype)下,有个toString的方法,记录着所有 数据类型(构造函数)
	.call作用是改this指向。让传入的对象,执行 “根”原型的toString方法

也可以在Array.prototype上添加一个myflatten属性

<script>
    var arr = [[12, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]]];
    Array.prototype.myflatten = function(){
        let _arr = this;
        let nArr = [];
        let toStr = {}.toString;

        _arr.forEach(function(item){
            toStr.call(item) === '[object Array]' 
                ? nArr = nArr.concat(item.myflatten()) 
                : nArr.push(item)
        })

        return nArr;
    }
    console.log(arr.myflatten()); // [12, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14]
    console.log(Array.from(new Set(arr.myflatten().sort((a, b) => a - b ))));
    // [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]
</script>

方法二:reduce()

array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 第一个参数是一个函数,每一次运行返回的结果会将作为参数传入;第二个参数是传递给函数的初始值,会赋给total。

举个例子具体感受以下reduce()的作用吧!

    let arr=[1,2,5,9,12,13,15];
    arr.reduce(function(prev,next){
        console.log("prev:",prev,"next:",next);
        return prev+next;
    },100)

结果如下:
prev: 100 next: 1
prev: 101 next: 2
prev: 103 next: 5
prev: 108 next: 9
prev: 117 next: 12
prev: 129 next: 13
prev: 142 next: 15

首先prev的初值就是100,next的初值为1。运行一次,所返回的值就是下一次prev的值,而next的值则是依次遍历数组的值。所以第一次运行时 prev:100;next:1;第二次运行时 prev:100+1=101;next:2; 第三次运行时 prev:101+2=103;next:5;以此类推…最终得出结果。

我们可以利用reduce这个特点进行对数组的扁平化,在Array.prototype上添加一个myflatten属性,,myflatten属性返回一个由于调用reduce这个API而得到的一个扁平化数组,给reduce的第二个参数初始值赋一个空数组,reduce第一个参数的形参prev与next进行拼接,拼接前需要判断next是否是一个数组,如果next是一个数组则需要调用此数组的myflatten属性进行扁平化,继续执行判断(也就是递归),如果next不是数组则直接与prev拼接,最后返回prev与next 的拼接数组
代码如下:

<script>
    var arr = [[12, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]]];
    Array.prototype.myflatten = function () {
        let _arr = this;
        let toStr = {}.toString;
        return _arr.reduce(function (prev, next) {
            return prev.concat(toStr.call(next) === "[object Array]" ? next.myflatten() : next)
        }, [])
    }
    console.log(arr.myflatten()); // [12, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14]
    console.log(Array.from(new Set(arr.myflatten())).sort((a,b)=>a-b));
    // [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]
</script>

也可以封装成一个函数进行扁平化:

    var arr = [[12, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]]];
    let myflatten=(arr)=> {
        return arr.reduce((prev, next)=>{
            return prev.concat({}.toString.call(next) === "[object Array]" ? myflatten(next) : next)
        }, [])
    }
    console.log(myflatten(arr)); // [12, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14]
    console.log(Array.from(new Set(myflatten(arr))).sort((a,b)=>a-b));
    // [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值