JavaScript中数组去除重复元素——数组去重

本文详细介绍五种常见的数组去重方法,包括最简单数组去重法、对象键值法、排序后相邻去除法、数组下标法及优化遍历数组法,帮助读者掌握不同场景下的最优去重策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面给大家介绍数组去重的几种常见方法

一、最简单数组去重法

// 最简单数组去重法
/*
* 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中
* IE8以下不支持数组的indexOf方法
* */
function unique(arr){
    var temp = []; //一个新的临时数组
    for(var i = 0; i < arr.length; i++){
    	// 用indexOf方法判断元数组中的每个元素是否在新的临时数组中存在
        if(temp.indexOf(arr[i]) == -1){
        	// 不存在就存入临时数组中
            temp.push(arr[i]);
        }
    }
    return temp;
}
var arr = [1,1,2,2,4,9,6,7,5,2,"a","a",3,5,6,5];
console.log(unique(arr));

在这里插入图片描述

二、对象键值法去重

数组也是一个对象

/*
* 速度最快, 占空间最多(空间换时间)
*
* 该方法执行的速度比其他任何方法都快, 就是占用的内存大一些。
* 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,
* 不是的话给对象新增该键并放入新数组。
* 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”,
* 不同的键可能会被误认为一样,例如n[val]-- n[1]、n["1"];
* 解决上述问题还是得调用“indexOf”。*/
function unique(arr){
    var temp = {}, r = [], len = array.length, val, type;
    for (var i = 0; i < len; i++) {
        val = arr[i];
        type = typeof val;
        if (!temp[val]) {
            temp[val] = [type];
            r.push(val);
        } else if (temp[val].indexOf(type) < 0) {
            temp[val].push(type);
            r.push(val);
        }
    }
    return r;
}

var arr = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniqun(arr));

在这里插入图片描述

三、排序后相邻去除法

/*
* 给传入数组排序,排序后相同值相邻,
* 然后遍历时,新数组只加入不与前一值重复的值。
* 会打乱原来数组的顺序
* */
function unique(arr){
    arr.sort();
    var temp=[arr[0]];
    for(var i = 1; i < arr.length; i++){
        if( arr[i] !== temp[temp.length-1]){
            temp.push(arr[i]);
        }
    }
    return temp;
}
var arr = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(unique(arr));

在这里插入图片描述

四、数组下标法

/*
*
* 还是得调用“indexOf”性能跟方法1差不多,
* 实现思路:如果当前数组的第i项在当前数组中第一次出现的位置不是i,
* 那么表示第i项是重复的,忽略掉。否则存入结果数组。
* */
function unique(arr){
    var temp = [];
    for(var i = 0; i < arr.length; i++) {
        //如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
        if(arr.indexOf(arr[i]) == i){
            temp.push(arr[i])
        }
    }
    return temp;
}
var arr = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(unique(arr));

在这里插入图片描述

五、优化遍历数组法

// 思路:获取没重复的最右一值放入新数组
/*
* 推荐的方法
*
* 方法的实现代码相当酷炫,
* 实现思路:获取没重复的最右一值放入新数组。
* (检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)*/
function unique(arr){
    var temp = [];
    var index = [];
    var l = arr.length;
    for(var i = 0; i < l; i++) {
        for(var j = i + 1; j < l; j++){
            if (arr[i] === arr[j]){
                i++;
                j = i;
            }
        }
        temp.push(arr[i]);
        index.push(i);
    }
    return temp;
}
var arr = [1,2,2,3,5,3,6,5];
console.log(unique(arr));

在这里插入图片描述

### 使用 JavaScript 实现移除数组中的复项 在编程中,可以通过多种方式实现移除数组中的复项。以下是几种常见的方法及其原理: #### 方法一:利用 `Set` 数据结构 `Set` 是一种集合数据结构,它会自动并存储唯一的值。通过将其转换回数组的方式可以轻松完成。 ```javascript function removeDuplicatesUsingSet(arr) { return [...new Set(arr)]; } let array = [1, 2, 3, 4, 3, 2, 1]; console.log(removeDuplicatesUsingSet(array)); // 输出: [1, 2, 3, 4] ``` 这种方法的时间复杂度主要取决于创建 `Set` 的过程,通常为 O(n),其中 n 表示数组长度[^1]。 --- #### 方法二:使用 `filter` 和 `indexOf` 此方法基于数组的索引来判断某个元素是否首次出现。 ```javascript function removeDuplicatesUsingFilter(arr) { return arr.filter((item, index) => arr.indexOf(item) === index); } let array = [1, 2, 3, 4, 3, 2, 1]; console.log(removeDuplicatesUsingFilter(array)); // 输出: [1, 2, 3, 4] ``` 该方法的核心在于每次调用 `arr.indexOf(item)` 来查找当前元素第一次出现的位置。如果当前位置等于其首次出现位置,则保留;否则丢弃。由于嵌套循环的存在,时间复杂度较高,约为 O(n²)。 --- #### 方法三:双指针法(适用于已排序数组) 对于已经排序好的数组,可采用双指针技术高效地移除复项。具体做法是维护两个指针分别指向不同部分的数据区域,并逐步更新慢速指针所对应的值。 ```javascript function removeDuplicatesInSortedArray(nums) { if (nums.length === 0) return 0; let slow = 0; for (let fast = 1; fast < nums.length; fast++) { if (nums[slow] !== nums[fast]) { slow++; nums[slow] = nums[fast]; } } return slow + 1; } // 测试用例 let sortedArray = [1, 1, 2, 2, 3, 4, 4, 5]; removeDuplicatesInSortedArray(sortedArray); console.log(sortedArray.slice(0, removeDuplicatesInSortedArray(sortedArray))); // 输出: [1, 2, 3, 4, 5] ``` 这种策略特别适合于大规模数据集上的操作,因为它仅需单次遍历整个列表即可达到目的,因此具有较低的时间开销——O(n)[^2]^。 --- #### 方法四:借助哈希表辅助空间优化版本 虽然上述三种方案各有优劣之处,但在某些特定情况下可能还需要考虑额外的空间消耗问题。下面介绍另一种思路即引入对象作为临时容器保存遇到过的键名从而进一步减少内存占用量的同时保持较高的执行效率: ```javascript function removeDuplicatesWithHash(arr){ const hashTable={}; const result=[]; for(let elem of arr){ if(!hashTable.hasOwnProperty(elem)){ hashTable[elem]=true; result.push(elem); } } return result; } const arrayWithDups=[9,'a',8,'b','c',7,'d','e',6,'f']; console.log(removeDuplicatesWithHash(arrayWithDups));//输出:[9,"a",8,"b","c",7,"d","e",6,"f"] ``` 这里定义了一个空的对象用于追踪哪些项目已经被加入到最终的结果集中了如果没有发现相同的则追加进反之忽略之故而实现了我们的目标同时兼顾性能表现良好因为查询属性存在与否的操作平均来说是非常快速接近常数级别所以总体上也是线性的复杂程度即O(N)[^3]. --- ### 总结 以上介绍了四种不同的解决方案来应对如何掉给定序列里面的冗余成分这个问题每种都有各自的特点以及适用范围开发者应当根据实际需求选取最合适的那一个比如当面对的是无序状态下的整型数字串列那么运用内置函数配合散列表可能是最佳选项而对于那些预先经过排列整理后的材料而言采取两头夹击式的扫描机制无疑更加经济实惠既节省了计算资源又提高了工作效率.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值