首页 > 其他分享 >【面试题】数组去重你想到几种办法呢?

【面试题】数组去重你想到几种办法呢?

时间:2023-07-01 11:35:09浏览次数:45  
标签:面试题 indexOf res 几种 API let 数组 array

前言

你是否在面试的过程中被考到过给你一个数组让你去掉重复项呢?当时你的脑海里除了用Set实现之外,你还与面试官讲了什么去重的方法呢?你能否封装来一个可复用的数组去重api呢?依稀记得当时我被问到这个问题的时候,我也没回答出很多种解决办法。那下面我来总结一下对于数组去重这道简单的面试题时,我们可以回答的方法有什么吧。

数组去重

1. 不使用数组API方法

首先我来介绍一种不是用数组身上的API的去重解法,代码如下:

var array = ['1', 1, '1', '1', '2', 2]
function unique(array) {
    let res = []
    for(let i = 0; i < array.length; i++){
        for( var j = 0; j < res.length; j++){
            if(array[i]  === res[j]){
                break;
            }
        }
        if(j === res.length){
            res.push(array[i])
        }
    }
    return res 
}
console.log(unique(array)); // [ '1', 1, '2', 2 ]

既然不使用数组自带的API方法,那我们首先考虑的就是用双重for循环了,如上述代码:

  1. 我们准备了一个空的结果数组
  2. 我们对需要去重的数组进行循环
  3. 在第一层数据中再套一层循环,根据下标判断结果数组内是否有重复项。

我们调用该方法,打印结构如上述代码的注解处,成功的实现了对数组的去重。

2. 使用 indexOf

既然有不使用数组API的,那就肯定有使用数组API的,下面看我使用indexOf完成数组的去重,代码如下:

var array = ['1', 1, '1', '1', '2', 2]
function unique(array) {
    let res = []
    for (let i = 0; i < array.length; i++) {
        if (res.indexOf(array[i]) === -1) { // 返回找到的第一个值得下标
            res.push(array[i])
        }
    }
    return res
}
console.log(unique(array))// [ '1', 1, '2', 2 ]

如上述代码, 我们巧妙了使用了indexOf查找结果数组中是否已经存在,如果不存在才向结果数组中添加,实现了数组去重。

在上述代码的基础上,我们还可以转变一下,将for循环内的语句改为

if (array.indexOf((array[i])) == array.lastIndexOf(array[i])) {
    i++
} else {
    array.splice(array.lastIndexOf(array[i]), 1)
}

不新增其他变量,直接通过indexOf和lastIndexOf判断该值是否在原数组内为唯一值,从而直接修改原数组,实现数组的去重。

3. 使用 sort

对于数组去重,我们除了通过下标找出是否有重复项之外,我们还可以先排序,然后在判断前后项是否相同来实现去重,代码如下:

var  array = [1, 3, 5, 4, 2, 1, 2, 4, 4, 4]
function unique(array) {
    let res = []
    let sortedArray = array.concat().sort() //concat() 返回新的数组
    let seen;
    for (let i = 0; i < sortedArray.length; i++) {
        if (!i || seen !== sortedArray[i]) {
            res.push(sortedArray[i])
        }
        seen = sortedArray[i]
    }
    return res
}
console.log(unique(array)); // [ 1, 2, 3, 4, 5 ]

如上述代码, 我们先获取一个排好序的新数组,再对新数组进行循环,判断保存前一个值的seen与当前值是否相同来实现数组去重。

温馨小提示: 由于数组的排序方法不能区分数组和字符串,所以想要使用此方法必须要保证数组的值的类型相同,不然会出bug

4. 使用 filter

既然都用到了sort排序了,那我直接抬出ES6数组新增的filter过滤器API也不过分吧,代码如下:

var array = ['1', 1, '1', '1', '2', 2]
function unique(array) {
    let res = array.filter((item, index, array) => {
        return array.indexOf(item) === index
    })
    return res
}
console.log(unique(array)); // [ '1', 1, '2', 2 ]

如上述代码,filter直接使用array.indexOf(item) === index作为过滤条件返回出一个新的数组,实现数组去重。

如上述代码,我们结合了 indexOf方法作为过滤条件,那我们也可以结合一下sort方法吧,直接使用一行代码就解决了数组的去重。代码如下:

function unique(array) {
    return array.concat().sort().filter((item, index, array) => !index || item !== array[item - 1])
}
console.log(unique(array)); // [ '1', 1, '2', 2 ]

5. 使用Set、Map、或者对象

除了上述的通过数组API和不使用数组API的方法外,我们还能想到的就是借助对象来实现数组的去重。使用Set数据结构是我们最容易想到的办法,使用Map与对象方法的相似,都是以数组的值作为key,再将所有的可以取出来组成一个数组。 我就不给小伙伴们演示代码了,感兴趣的小伙伴可以自己动手试试。

(对于对象的key只能为字符串这个问题,我们可以换个思路,将下标存为key,值存为value,判断不同key的值相不相同来实现数组去重。我们还可以在存key时加上其类型,然后进行一次转换。)

自己封装一个去重API

在介绍上述数组去重的方法后,我们再来总结一下,将其融合成一个有复用性,而且还可以适用不同情况的API方法。

我来介绍一下如下我封装的一个数组去重的API方法,

  1. 该方法可接受三个参数,第一个参数为需要去重的数组,第二个参数为该数组是否为排好序的数组,第三个参数为一个回调函数
  2. 该回调函数也有三个参数,分别为值,下标,需要去重数组。该回调函数的作用是方便用户对数组进行一些额外的处理(例如将大写转为小写)
  3. 第二,三参数可不传递。
var array = [1, 2, '1', 'a', 'A', 2, 1]
var array2 = [1, 1, '1', 2, 2]
function uniq(array, isSorted, iteratee) {
    let  seen = []
    let res = []
    for(let i = 0; i < array.length; i++){
        let computed = iteratee ? iteratee(array[i], i,array) : array[i]
        if(isSorted) {
            if(!i || seen !== array[i]){
                res.push(array[i])
            }
            seen = array[i]
        }else if(iteratee) {
            if(seen.indexOf(computed) === -1){
                seen.push(computed)
                res.push(computed)
            }
        }
        else {
            if(res.indexOf(array[i]) === -1) {
                res.push(array[i])
            }
        }
    }
    return res
}
let result = uniq(array, false, function(item, index, arr){
    return typeof item == 'string' ? item.toLowerCase() : item
})
console.log(result); // [ 1, 2, '1', 'a' ]
console.log(uniq(array2, true)); // [ 1, 2 ]

总结

对于数组的去重,当我们能在面试中说到这个多方法的话,这道面试题也就过了,虽然这道面试不难,但如果我们想要想到这个多方法的话,还是需要许多知识储备的。

 


标签:面试题,indexOf,res,几种,API,let,数组,array
From: https://blog.51cto.com/u_14627797/6598566

相关文章

  • CSS中几种定位的简单描述与对比
    静态定位(static):position属性的默认值为static,会忽略top,bottom,left,right或者z-index声明。相对定位(relative)与绝对定位(absolute): 相对定位偏移参考元素是元素本身,而绝对定位以父辈元素中最近的定位元素为参考坐标(父辈没有定位元素则参考html),因此常用“子......
  • 稀疏数组应用场景
    基本介绍:当一个数组中大部分元素为0,或为同一个值的数组时,可以用稀疏数组来保存该数组处理方法:举例说明:......
  • 最新上海电信 SDN 光猫实现外网访问的几种方法
    上海电信黑色的SDN光猫,也叫SDN网关,其网页后台没有任何设置功能,致电客服要求改桥接也很麻烦。如果家有NAS、服务器等设备,如何才能实现外网访问呢?经过虫子菌实测,如果SDN光猫在1.4版本以上,通过光猫APP客户端设置虚拟服务器、DMZ或UPnP,任意一种方式都能实现外网访问,并且不影响已......
  • 大数据面试题集锦-Hadoop面试题(三)-MapReduce
    你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案。如果你需要更多的面试经验和面试题,关注一下"张飞的猪大数据分享"吧,公众号会不定时的分享相关的知识和资料。目录1、谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化?2、FileInputFormat切片机制3、......
  • C语言初阶-数组
    1.一维数组的创建和初始化1.1数组的创建数组是一组相同类型元素的集合数组的创建方式:type_t  arr_name [const_n];//type_t数组元素类型 arr_name数组名const_n常量表达式或常量,用来指定数组的大小[]基本语法形式intarr[20];charch[5];doubledate1[20];doubleda......
  • 微服务异常处理的几种方法
    创建全局异常处理器@RestControllerAdvice//声明当前这个类是全局异常处理器publicclassGlobalExceptionHandler{/***@ExceptionHandler指定当前这个方法就是一个异常处理方法,并且指定当前方法可以处理的异常类型*@parame*@return*/......
  • 面试题
    银行面1.ssrf怎么getshell2.waf绕过3.sql注入原理和修复4.app渗透测试5.最深刻的一次渗透经历6.有什么想问我的?7.cnvd证书情况8.sdl安全开发测试 qiandenghu面1.等保的整个流程2.风险评估怎么做3.个人最擅长的方向4.攻防yalian的时候担当什么角色5.有没有写过完......
  • Vue3 reactive 操作数组 响应性(数组变了,但页面显示没变)问题
    问题代码:tableTemplates:Array<HkTaskTemplateEntity>=reactive([]);//删除方法的一部分,根据templateId删除数组数据this.tableTemplates=this.tableTemplates.filter(item=>templateId!==item.templateId);删除后tableTemplates数组中对象减少,但vue页面显示数据......
  • 【快应用】快应用加桌的几种实现方式
     【关键词】快应用、桌面快捷方式、Deeplink【问题背景】在快应用开发和使用过程中,我们对于喜欢的应用总想把它添加到桌面,方便下次快速进入。那么,有几种实现方式呢?【实现方法】1.Deeplink加桌快应用提供标准的Deeplink入口,可以实现点击web页面的链接启动快应用。安装快应用中心后......
  • 40 个 Nginx 常问面试题
    Nginx是一个轻量级/高性能的反向代理Web服务器,用于HTTP、HTTPS、SMTP、POP3和IMAP协议。他实现非常高效的反向代理、负载平衡,他可以处理2-3万并发连接数,官方监测能支持5万并发,现在中国使用nginx网站用户有很多,例如:新浪、网易、腾讯等。 N......