JavaScript专题之二:数组去重

JavaScript专题之二:数组去重

目录

一、双层循环(暴力方法)二、indexOf和includes三、排序去重四、filter五、键值对(key-value)六、ES6七、一些问题参考

写在最后

(相关免费学习推荐:javascript视频教程)

在这里插入图片描述

立即学习“Java免费学习笔记(深入)”;

一、双层循环

const unique = (arr)=>{    for(let i = 0; i < arr.length; i++){        for(let j = i + 1; j {    var arr = [1, '1', '1', 1, 2, true, false, true, 3, 2, 2, 1];    var newArr = [];    for(let i = 0; i < arr.length; i++){        for(var j = 0; j < newArr.length; j++){ // 注意var声明的j            if(arr[i] === newArr[j]) break; // 新数组已存在当前值        }        if(j === newArr.length){ // 此时j和newArr长度相等,没有被中断            newArr.push(arr[i]);        }    }    return newArr;}unique([1, '1', '1', 1, 2, true, false, true, 3, 2, 2, 1]); // [ 1, '1', 2, true, false, 3 ]

登录后复制

核心点:

时间复杂度:O(n^2)上面的两种方法都是两次循环遍历,处理方式略有不同上述实现方式确实不是最佳选择,但它胜在兼容性好啊~

二、indexOf和includes

2.1 indexOf简化一层循环判断

核心点:

如果需要返回原数组,则可以在indexOf方法找到重复项时(不等于它首次出现的位置)时利用splice移除indexOf:返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。indexOf(ele, fromIndex)  ele:要查找的元素fromIndex:查找元素的起始位置,默认为0,允许负数,-2表示从倒数第二个元素开始查找返回一个下标(number)

代码:

const unique = (arr) => {    var res = [];    for (let i = 0; i < arr.length; i++){        if(res.indexOf(arr[i]) === -1 ){            res.push(arr[i]);        }    }    return res;}

登录后复制

2.2 includes简化一层循环判断

核心点:

具体的是要返回原数组还是新数组大家可以自行组合~includes:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回falseincludes(ele, fromIndex)  ele:要查找的元素fromIndex:指定索引处开始查找。默认为 0,如果为负值,从末尾开始往前跳 fromIndex 的绝对值个索引。。返回结果(bool)

代码:

const unique = (arr) => {    var res = [];    for (let i = 0; i < arr.length; i++){        if(!res.includes(arr[i])){            res.push(arr[i]);        }    }    return res;}

登录后复制

2.3 indexOf和includes对于当前场景的选择

在这里我们推荐使用includes来查找元素:

返回值可以直接作为if的条件语句,简洁

if(res.indexOf(arr[i]) !== -1 ){ todo }// orif(res.includes(arr[i])){ todo }

登录后复制

识别NaN

如果数组中有NaN,你又正好需要判断数组是否有存在NaN,这时你使用indexOf是无法判断的,你必须使用includes这个方法。

var arr = [NaN, NaN];arr.indexOf(NaN); // -1arr.includes(NaN); // true

登录后复制

识别undefined

如果数组中有undefined值,includes会认为空的值是undefined,而indexOf不会。

var arr = new Array(3);console.log(arr.indexOf(undefined)); //-1console.log(arr.includes(undefined)) //true

登录后复制

三、排序去重

核心点:

数组排序后,相同的元素会相邻,所以如果当前元素与它的相邻元素不同,就存入到新数组中;相比于indexOf,只需要一层循环;concat会拼接数组,并返回新数组;sort()排序是通过按照转换为的字符串的各个字符的Unicode位点进行排序。所以很难保证它的准确性;

代码:

var arr = [1, 1, '1'];function unique(arr) {    var res = [];    var sortedArr = arr.concat().sort();    var last;    for (var i = 0; i < sortedArr.length ; i++) {        // 如果是第一个元素或者相邻的元素不相同        if (!i || last !== sortedArr[i]) {            res.push(sortedArr[i])        }        last = sortedArr[i]; // 记录上一个值    }    return res;}console.log(unique(array));

登录后复制

四、filter

核心点:

filter:方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素(返回测试函数成立的元素)filter(callback, thisArg):callback接受三个参数:element-当前正在处理的元素,index-当前元素索引,array-调用了filter的数组本身thisArg:执行 callback 时,用于 this 的值。
利用filter我们可以在代码层面简化一下外层循环:

代码:

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

登录后复制

结合排序的思路:

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

登录后复制

五、键值对(key-value)

前面提到的几种方式总结下来大致分为

非排序数组,两次遍历判断(遍历、查询)排序数组,相邻元素比较

我们再提出一种方式,利用Object对象 key-value的方式,来统计数组中元素出现的个数,初步判断逻辑也有两种

拿[1,1,1,2,2,3,’3′]举例:

统计每个元素出现的次数,obj:{1: 3, 2: 2, 3: 3}, 返回这个obj的key而不管他们的value只元素首次出现,再次出现则证明他是重复元素

5.1 统计次数
var arr = [1, 2, 1, 1, '1', 3, 3];const unique = function(arr) {    var obj = {};    var res = [];    arr.forEach(item => {        if (!obj[item]) {            obj[item] = true;            res.push(item);        }    });    return res;}console.log(unique(arr)); // [1, 2, 3]

登录后复制

5.2 结合filter
var arr = [1, 2, 1, 1, '1'];const unique = function(arr) {    var obj = {};    return arr.filter(function(item, index, arr){        return obj.hasOwnProperty(item) ? false : (obj[item] = true)    })}console.log(unique(arr)); // [1, 2]

登录后复制

5.3 key: value存在的问题

对象的属性是字符串类型的,即本身数字1和字符串‘1’是不同的,但保存到对象中时会发生隐式类型转换,导致去重存在一定的隐患。

考虑到string和number的区别(typeof 1 === ‘number’, typeof ‘1’ === ‘string’),

所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题:

var arr = [1, 2, 1, 1, '1', 3, 3, '2'];const unique = function(arr) {    var obj = {};    var res = [];    arr.forEach(item => {        if (!obj[typeof item + item]) {            obj[typeof item + item] = true;            res.push(item);        }    });    return res;}console.log(unique(arr)); // [ 1, 2, '1', 3, '2' ]

登录后复制

六、ES6

随着 ES6 的到来,去重的方法又有了进展,比如我们可以使用 Set 和 Map 数据结构。

6.1 Set

Set:它允许你存储任何类型的唯一值,无论是原始值或者是对象引用

代码:

var arr = [1, 2, 1, '1', '2'];const unique = function(arr) {   return Array.from(new Set(arr));}console.log(unique(arr)); // [ 1, 2, '1', '2' ]

登录后复制

简化1:

function unique(array) {    return [...new Set(array)];}

登录后复制

简化2:

var unique = (a) => [...new Set(a)]

登录后复制

6.2 Map

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

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

function unique (arr) {    const newMap = new Map()    return arr.filter((a) => !newMap.has(a) && newMap.set(a, 1));}

登录后复制

写到这里比较常规的数组去重方法就总结的差不多了,如果需要更强大的去重方法,我们需要对他们进行组合,而且因为场景的不同,我们所实现的方法并不一定能涵盖到

相关免费学习推荐:javascript(视频)

以上就是JavaScript专题之二:数组去重的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2717275.html

(0)
上一篇 2025年3月7日 22:02:51
下一篇 2025年3月6日 03:27:55

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • JavaScript专题之三:防抖

    目录 一、为什么需要防抖二、防抖的原理三、防抖简单实现四、防抖进阶 写在最后 (相关免费学习推荐:javascript视频教程) 一、为什么需要防抖 立即学习“Java免费学习笔记(深入)”; 高频的函数操作可能产生不好的影响如:resiz…

    2025年3月7日 编程技术
    200
  • JavaScript专题之五:深浅拷贝

    了解拷贝背后的过程,避免不必要的错误,Js专题系列之深浅拷贝,我们一起加油~ 目录 一、拷贝示例二、浅拷贝三、深拷贝的方法? 四、自己实现深浅拷贝 免费学习推荐:javascript视频教程 一、拷贝示例 立即学习“Java免费学习笔记(深…

    2025年3月7日 编程技术
    200
  • JavaScript专题之六:类型检测

    javascript专题之数据类型检测的那些事 目录 一、typeof二、instanceof三、constructor四、stringTag是什么?五、实现几个数据检测的方法 写在最后 (免费学习推荐:javascript视频教程) 立即…

    2025年3月7日
    200
  • javascript字符串怎么截取前四位

    javascript字符串截取前四位的方法:1、使用“str.slice(0, 4)”来截取字符串前四位;2、使用“str.substr(0,4)”来截取字符串前四位;3、使用“str.substring(0,4)”来截取字符串前四位。 本…

    2025年3月7日 编程技术
    200
  • JavaScript专题之七:类型转换

    目录 前言一、类型转换是什么?二、原始值转换的基本规则三、对象转字符串和数字四、常见的类型转换运算符五、常见的类型转换操作 写在最后 (免费学习推荐:javascript视频教程) 前言 立即学习“Java免费学习笔记(深入)”; 在了解类…

    2025年3月7日 编程技术
    200
  • JavaScript专题之八:数组扁平化

    目录 一、递归二、reduce三、apply+some四、ES6展开运算符五、toString六、正则七、实现自己的扁平化工具方法写在最后 (免费学习推荐:javascript视频教程) 一、递归 for循环是我们在进行数组操作时最容易想到…

    2025年3月7日
    200
  • JavaScript 专题之九:数组中查找指定元素

    文章目录 一、findIndex 和 findLastIndex1.1 findIndex1.2 findLastIndex1.3 合并 findIndex 和 findLastIndex二、sortIndex2.1 遍历2.2 二分法三、…

    2025年3月7日
    200
  • js如何获取session中的值

    js获取session中值的方法:1、可以做一个AJAX来请求服务器, 返回session中的值;2、可以在JSP中使用【】这种标签来获取session中的值。 本教程操作环境:windows7系统、javascript1.8.5版,DEL…

    2025年3月7日
    200
  • JavaScript中怎么换行

    js中换行的方法:1、使用【】换行符,代码为【alert(“第一行第二行”)】;2、使用【】换行符,代码为【alert(“第一行第二行”)】;3、使用HTML的【】标签。 本教程操作环境:wi…

    2025年3月7日
    200
  • JavaScript的代码简洁技巧

    这篇文章主要是想和大家一起学习一下,工作之中有哪些让我们眼前一亮的JavaScript代码简洁小技巧。 注意:下面的代码对比没有绝对的正确和错误,有些写法的使用场景会比较单一,根据大家的习惯和喜好判断即可,如果有更好或不同意见欢迎留言交流哦…

    2025年3月7日
    200

发表回复

登录后才能评论