关于javascript:面试题数组去重引出的多元宇宙😏

1.怎么解决一个数组去重问题

我看了很多面试相干的问题,发现数组去重呈现过几次,这里就对数组去重问题进行一个总结。并且进行扩大。请肯定要看到第二章!

问题形容:数组去重,顾名思义就是,把数组里的反复数值去除,使其多个雷同的数值变为一个,最初使数组里不含有反复数值。

举个例子:有个数组:[1,2,3,4,4,5,5,5,6,7],数组去重后就变为[1,2,3,4,5,6,7]

该问题有很多解决办法,这里将一一列出,并且会对其个别重要知识点进行扩大

解法将由浅入深😏,肯定要看到最初几个解法!

🤔 解法1:

应用双重for和splice

// 双重for加splice
function unique(arr){            
    for(var i=0; i<arr.length; i++){
        for(var j=i+1; j<arr.length; j++){
            if(arr[i]==arr[j]){         
            //第一个等同于第二个,splice办法删除第二个
                arr.splice(j,1);
                j--;
            }
        }
    }
return arr;
}

🤔 解法2

应用indexof办法和新数组

//应用indexof
function unique(arr) {
    var array = [];//用新数组来装
    for (let i = 0; i < arr.length; i++) {
        if (array.indexOf(arr[i]) === -1) {
            //indexof返回-1示意在新数组中不存在该元素
            array.push(arr[i])//是新数组里没有的元素就push入
        }
    }
    return array;
}

应用includes也能够判断是否含有某值

function unique(arr) {
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes(arr[i]) ) {
            //includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
  • indexOf()办法返回在数组中能够找到一个给定元素的第一个索引,如果不存在,则返回-1。有两个参数,第一个参数是要查找的元素,第二个参数可选,是开始查找的地位。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组开端的一个对消,即-1示意从最初一个元素开始查找,-2示意从倒数第二个元素开始查找,查找程序依然是从前向后查问数组。如果对消后的索引值仍小于0,则整个数组都将会被查问。其默认值为0
  • includes() 办法用来判断一个数组是否蕴含一个指定的值,依据状况,如果蕴含则返回 true,否则返回false。其也有两个参数,第一个是要查找的元素,第二个可选,是开始查找的地位,与indexof雷同的是,第二个参数为负值的话,就从开端开始往前跳 参数 的绝对值个索引,而后往后搜查。默认为 0

🤔 解法3

应用sort办法先排序,使雷同的元素都相邻

function unique(arr) {
    arr = arr.sort((a, b) => a - b)//sort先按从小到大排序
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}

sort办法用于从小到大排序(返回一个新数组),其参数中不带以上回调函数就会在两位数及以上时呈现排序谬误(如果省略,元素依照转换为的字符串的各个字符的Unicode位点进行排序。两位数会变为长度为二的字符串来计算)。所以本人要写一个排序规范,当回调函数返回值大于0时两个值调换程序。

🤔 解法4

ES6 提供了新的数据结构 Set。Set能够非常简单的去重

function unique(arr) {
    const result=new Set(arr);
    return [...result];
    //应用扩大运算符将Set数据结构转为数组
}

Set对象是值的汇合,你能够依照插入的程序迭代它的元素。 Set中的元素只会呈现一次,即 Set 中的元素是惟一的。

🤔 解法5

应用Map

function unique(arr) {
    let map = new Map();
    let array = new Array();  // 数组用于返回后果
    for (let i = 0; i < arr.length; i++) {
      if(map.has(arr[i])) {  // 如果有该key值
        map.set(arr[i], true); 
      } else { 
        map.set(arr[i], false);   // 如果没有该key值
        array.push(arr[i]);
      }
    } 
    return array ;
}

Map 对象保留键值对,并且可能记住键的原始插入程序。任何值(对象或者原始值) 都能够作为一个键或一个值。

  • Map.prototype.has(key) 返回一个布尔值,示意Map实例是否蕴含键对应的值。
  • Map.prototype.set(key, value) 设置Map对象中键的值。返回该Map对象。

🤔 解法6

应用filter

function unique(arr) {
    return arr.filter(function (item, index, arr) {
        //以后元素,在原始数组中的第一个索引==以后索引值,否则返回以后元素
        //不是那么就证实是反复项,就舍弃
        return arr.indexOf(item) === index;
    })
}

filter英文意思是筛选,filter() 办法创立一个新数组, 其蕴含通过所提供函数实现的测试的所有元素。其回调函数蕴含三个参数(数组中以后正在解决的元素,在解决的元素在数组中的索引(可选),调用了 filter 的数组自身(可选))

🤔 解法7

应用reduce加includes

function unique(arr){
    let result=arr.reduce((acc,cur)=>{
        if(!acc.includes(cur)){
            acc.push(cur);
        }
        return acc;
    },[])//[]作为回调函数的第一个参数的初始值
    return result
}

2.数组去重解法7引出对于reduce的另一道面试题

reduce的用途很多,很重要,这里补上上面对reducer的知识点解释。

reduce介绍

MDN中对其的形容是:reduce() 办法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其后果汇总为单个返回值。其能做的性能很多,通过回调函数实现。

reduce的第一个参数是个回调函数,其有四个参数(累加器,以后值,以后索引,原数组),后两个参数可选。第二个参数是回调函数的第一个参数累加器的初始值(很重要)

留神:不给初始值,那么初始值就是原数组的第一个元素,计算从第二个元素开始。给了初始值就是从第一个元素开始

通过代码实现性能理解reduce与其回调函数的书写:

  • 为存储数值的数值进行累加求和
let result=[1,2,3,4].reduce((acc,cur)=>{
    return acc+cur;//acc为累加器(初始值为数组第一个元素),cur为以后元素
})
console.log(result);//输入10
//因为没初始值,所以从数组第二个元素开始计算,所以解决下面数组,回调函数共运行了3次
  • 累加求和时给初始值
let result=[1,2,3,4].reduce((acc,cur,index,o)=>{
    return acc+cur;
},10)
console.log(result);//输入20
//因为有初始值,所以从数组第一个元素开始计算,所以解决下面数组,回调函数共运行了4次
  • 按属性对object进行分类
const bills=[{type:'transfer',momey:233},
             {type:'study',momey:341},
             {type:'shop',momey:821},
             {type:'transfer',money:821},
             {type:'study',momey:821}
            ]
let result=bills.reduce((acc,cur)=>{
    if(!acc[cur.type]){//遇到不存在的类型,就新建一个空数组来装
        acc[cur.type]=[];//二维数组
    }
    acc[cur.type].push(cur)
    return acc;
},[])//为累加器设置初始值为空数组,作为分类用的容器
console.log(result);
//输入
[
  transfer: [{ type: 'transfer', momey: 233 },{ type: 'transfer', money: 821}],
  study: [ { type: 'study', momey: 341 }, { type: 'study', momey: 821 } ],
  shop: [ { type: 'shop', momey: 821 } ]
]

reduce相干面试题

🤔 题目形容:请应用原生 JavaScript 实现一个办法,判断 html 中呈现次数最多的标签,并统计这个次数。

知识点细化:

  • 获取所有标签:

    document.querySelector(*):列出页面内所有标签,*示意选择器*,也就是全副。

  • Object.entries():

    Object.entries()返回一个数组,其元素是与间接在object上找到的可枚举属性键值对绝对应的数组。属性的程序与通过手动循环对象的属性值所给出的程序雷同。简略的来说就是能够把对象的每个属性变为一个数组,这个数组里有两个值,一个为属性名,一个为属性值。例如:Object.entires({a:1,b:2,c:3})会失去[ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]

思路剖析:<br/>

1. 先取得含有所有标签的NodeList数组,而后将其加工为只有标签名的数组,接着应用reduce失去一个对象,以标签名为属性名,标签数量为属性值的对象。<br/>
2.将上一步失去的对象用Object.entires()变为个二维数组,再应用reduce对其解决,失去数量最多的那个标签(``比拟每个数组的tags[1],返回数组的tags[0]``)。

答案代码:

 window.onload=function(){
    // 最大数的思路是JS 必考的 应用reduce
    const maxBy=function(list,tag){
        return list.reduce(
            function(x,y){
                //依据reduce办法取得数量最大的那个标签
                return tag(x)>tag(y)?x:y
            }
            )
    }
    function getFrequentTag(){
        //失去reduce 须要的数组
        const tags=[...document.querySelectorAll('*')].map(x=>x.tagName).reduce((acc,tag)=>{
            acc[tag]=acc[tag]?acc[tag]+1:1;
            //数组存在该元素,就值+1,否则创立元素,设置值为1
            return acc;//失去以tag名为属性名,数量为属性值的对象
        },{})//初始值为对象
        return maxBy(Object.entries(tags),tag=>tag[1])
        //tag=>tag[1]这个函数示意return数组的第二个值,也就是标签的数量
    }
    console.log(getFrequentTag());
}

扩大:如何失去第二多的标签,以及数量第X大的标签呢?

对下面的解法进行进一步的优化,咱们要做的不在是失去最大,而是要失去任意大的标签!<br/>
应用sort办法改良

代码:

//取得第X多的标签

window.onload=function(){
    // 最大数的思路是JS 必考的 应用reduce
    const maxByx=function(list,tag,x){
        list=list.sort((a,b)=>{
            return tag(b)-tag(a);//数量从大到小排序
        })
        return list[x];
    }
    function getFrequentTag(){
        //失去reduce 须要的数组
        const tags=[...document.querySelectorAll('*')].map(x=>x.tagName).reduce((acc,tag)=>{
            acc[tag]=acc[tag]?acc[tag]+1:1;//数组存在该元素,就值+1,否则创立元素,设置值为1
            return acc;//失去以tag名为属性名,数量为属性值的对象
        },{})//初始值为对象
        return maxByx(Object.entries(tags),tag=>tag[1],1)
        //第三个参数用于指定要第几大的,这里指定第二大的
        //tag=>tag[1]这个函数示意return数组的第二个值,也就是标签的数量
    }
    console.log(getFrequentTag());
}

依据下面代码return maxByx(Object.entries(tags),tag=>tag[1],1),咱们只须要指定第三个参数值就可能失去咱们要的数量排名第X的的那个标签。<br/>
这里就实现了面试中对失去html中最大数量标签的升华了!

感激浏览,有好的倡议请肯定提出,感激感激,笔者最近也在筹备面试中!

参考文章:

如何获取页面呈现次数最多的 HTML 标签

JavaScript数组去重

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理