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,则整个数组都将会被查问。其默认值为0includes()
办法用来判断一个数组是否蕴含一个指定的值,依据状况,如果蕴含则返回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数组去重
发表回复