登录  /  注册
首页 > web前端 > js教程 > 正文

JavaScript专题之二:数组去重

coldplay.xixi
发布: 2021-03-03 10:23:45
转载
1470人浏览过

JavaScript专题之二:数组去重

目录

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

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

在这里插入图片描述

一、双层循环

const unique = (arr)=>{
    for(let i = 0; i {
    var arr = [1, '1', '1', 1, 2, true, false, true, 3, 2, 2, 1];
    var newArr = [];
    for(let i = 0; i <p><strong>核心点:</strong></p>
登录后复制
  • 时间复杂度:O(n^2)
  • 上面的两种方法都是两次循环遍历,处理方式略有不同
  • 上述实现方式确实不是最佳选择,但它胜在兼容性好啊~

二、indexOf和includes

2.1 indexOf简化一层循环判断

核心点:

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

代码:

const unique = (arr) =&gt; {
    var res = [];
    for (let i = 0; i <h5>2.2 includes简化一层循环判断</h5><p><strong>核心点:</strong></p>
登录后复制
  • 具体的是要返回原数组还是新数组大家可以自行组合~
  • includes:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false
  • includes(ele, fromIndex)  
    • ele:要查找的元素
    • fromIndex:指定索引处开始查找。默认为 0,如果为负值,从末尾开始往前跳 fromIndex 的绝对值个索引。。
    • 返回结果(bool)

代码:

const unique = (arr) =&gt; {
    var res = [];
    for (let i = 0; i <h5>2.3 indexOf和includes对于当前场景的选择</h5><p>在这里我们推荐使用includes来查找元素:</p><p><strong>返回值可以直接作为if的条件语句,简洁</strong></p><pre class="brush:php;toolbar:false">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 <p><strong>四、filter</strong></p><p><strong>核心点:</strong></p>
登录后复制
  • 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)

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

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

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

[1,1,1,2,2,3,'3']举例:

  1. 统计每个元素出现的次数,obj:{1: 3, 2: 2, 3: 3}, 返回这个objkey而不管他们的value
  2. 只元素首次出现,再次出现则证明他是重复元素
5.1 统计次数
var arr = [1, 2, 1, 1, '1', 3, 3];const unique = function(arr) {
    var obj = {};
    var res = [];
    arr.forEach(item =&gt; {
        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 =&gt; {
        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) =&gt; [...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) =&gt; !newMap.has(a) &amp;&amp; newMap.set(a, 1));}
登录后复制

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

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

以上就是JavaScript专题之二:数组去重的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:CSDN网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
关于CSS思维导图的课件在哪? 课件
凡人来自于2024-04-16 10:10:18
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号