1. 首页 > 笙耀百科 >

js去重的几种方式(js去重函数)

JaScript数组去重的几种方法效率测试

以下是我针对网上三种高效率方法总结与效率测试,如果大家有更好的意见或建议也可以提出,大家共勉学习。

js去重的几种方式(js去重函数)js去重的几种方式(js去重函数)


数组去重法1:

Array.prototype.unique1 = function(){

console.time("数组去重法1"); //记录开始执行的时间

var arr = [];//创建一个临时数组

var obj = {}; //创建一个空对象

for(var i = 0; i < this.length; i++){ //遍历当前要去重的数组

if(!obj[this[i]]){ //判断obj对象中是否存有当前项,没有则执行

arr.push(this[i]); //将当前项push到临时数组中

obj[this[i]] = 1; //将当前项存入obj对象

}}

console.timeEnd("数组去重法1"); //记录结束执行的时间

return arr;

}数组去重法2:

Array.prototype.unique2 = function(){

console.time("数组去重法2"); //记录开始执行的时间

var arr = []; //创建一个临时数组

for(var i = 0; i < this.length; i++){ //遍历当前要去重的数组

if(arr.indexOf(this[i]) == -1){ //判断临时数组中是否存有当前项,没有则执行

arr.push(this[i]); //将当前项push到临时数组中

}}

console.timeEnd("数组去重法2"); //记录结束执行的时间

return arr;

}数组去重法3:

Array.prototype.unique3 = function(){

console.time("数组去重法3"); //记录开始执行的时间

var arr = [this[0]]; //创建一个临时数组,并将要去重数组的项存入临时数组

for(var i = 1; i < this.length; i++) { //从要去重数组第二项开始遍历

if (this.indexOf(this[i]) == i){ //判断临时数组中是否存有当前项,没有则执行

arr.push(this[i]); //将当前项push到临时数组中

}}

console.timeEnd("数组去重法3"); //记录结束执行的时间

return arr;

}效率测试方法:

var arr1 = []; //创建一个要去重的数组

for(var i = 0; i < 200000; i++){ //遍历200000个数据

arr1.push(parseInt(Math.random() 10) + 1); //将所有数据返回为随机数(1-10之间)的数, 并push到要去重的数组中

}console.log(arr1.unique1()); //打印数组去重法1的执行时间

console.log(arr1.unique2()); //打印数组去重法2的执行时间

console.log(arr1.unique3()); //打印数组去重法3的执行时间

效率测试结果:

实例详解jascript数组去重的几种思路

数据去重的需求实际上像是lodash这些工具库已经有成熟完备的实现,并且可以成熟地运用于生产环境。但是这并不妨碍我们从思维拓展的角度出发,看看去重可以用几种思路去实现。本文主要和大家分享jascript数组去重的几种思路。

首先是常规的双层循环比对的思路实现

function doubleLoopUniq(arr) {

let result = [];

for (let i = 0, len = arr.length, isExist; i < len; i++) {

// 定义一个变量表示当前元素在 result 中是否存在。

isExist = false;

for (let j = 0, rLen = result.length; j < rLen; j++) {

if (result[j] === arr[i]) {

// 依次对result 中的元素 和 原数组元素进行比对。

isExist = true;

break;

}}

// 判断如果不存在,则将此元素插入result

!isExist && result.push(arr[i]);

}return result;

}借助 js内置的indexOf 进行去重

function indexOfUniq(arr) {

let result = [];

for (let i = 0, len = arr.length; i < len; i++) {

// 用indexOf 简化了二层循环的流程

if (result.indexOf(arr[i]) === -1) result.push(arr[i]);

}return result;

}排序后前后比对去重

function sortUniq(arr) {

let result = [], last;

// 这里解构是为了不对原数组产生副作用

[ ...arr ].sort().forEach(item => {

if (item != last) {

result.push(item);

last = item;

}});

return result;

}通过hashTable去重

function hashUniq(arr) {

let hashTable = arr.reduce((result, curr, index, array) => {

result[curr] = true;

return result;

}, {})

return Object.keys(hashTable).map(item => parseInt(item, 10));

}ES6 SET一行代码实现去重

function toSetUniq(arr) {

return Array.from(new Set(arr));

}splice 去重(直接作数组本身,带副作用)

function inPlaceUniq(arr) {

let idx = 0;

while (idx < arr.length) {

let compare = idx + 1;

while (compare < arr.length) {

if (arr[idx] == arr[compare]) {

arr.splice(compare, 1);

continue;

}++compare

}++idx;

}return arr;

}在nodejs下面简单跑个测试,看看哪个效率高~

let data = [];

for (var i = 0; i < 100000; i++) {

data.push(Math.random())

}// 实现一个性能测试的装饰器

function performanceTest(fn, descript) {

var a = new Date().getTime();

return function () {

fn.apply(this, [].slice.call(arguments, 0));

console.log(descript, new Date().getTime() - a)

}}

performanceTest(hashUniq, "hashTable")(data)

performanceTest(sortUniq, "sortUniq")(data)

performanceTest(toSetUniq, "toSetUniq")(data)

performanceTest(indexOfUniq, "indexOfUniq")(data)

performanceTest(doubleLoopUniq, "doubleLoopUniq")(data)

performanceTest(inPlaceUniq, "inPlaceUniq")(data)结果如下

hashTable 168ms

sortUniq 332ms

toSetUniq 80ms

indexOfUniq 4280ms

doubleLoopUniq 13303ms

inPlaceUniq 9977ms延伸思考: 如果数组内的元素是对象该怎么去重呢?

既然是引用类型,那么不免会使用到deepEqual,固然这种思路可以解答这道问题,但难免不够高效。

从上面的测试中也可见通过new Set 和 hashTable 去重是效的。

所以毫无疑问,我们要基于这两种方式去改造,我想用的是hashTable,

另一方面,为了降低深度比较带来的耗时,我尝试用JSON.stringify 将引用类型转化为基本类型。

function collectionUniq(collection) {

let hashTable = {};

collection.forEach(item => {

hashTable[JSON.stringify(item)] = true;

})

return Object.keys(hashTable).map(item => JSON.parse(item))

}那么问题来了,我们都知道对象的属性是无序的,假如数据是这种情况,那就GG了。

let collection = [ { a: 1, b: 2, c: 3 }, { b: 2, c: 3, a: 1 } ]有一种toHash的思路,在对这个数组进行一次基本的去重之后,为了保证准确,

先遍历JSON 字符串 =>

通过 charCodeAt()拿到每个字符串 的 unicode 编码 =>

相加得到一个总数,再两两进行比较,数值相等的就是重复的,这样就达到去重的效果了。

function toHash(obj) {

let power = 1;

let res = 0;

const string = JSON.stringify(obj, null, 2);

for (let i = 0, l = string.length; i < l; i++) {

switch (string[i]) {

case '{':

power = 2

break

case '}':

power /= 2

break

case ' ':

case '

':

case '

':

case '\t':

break

default:

res += string[i].charCodeAt(0) power

}}

return res

}这只是一个实现基本的思路,有很大的改进空间,为了减少hash碰撞的可能,可以对一些特殊字符进行权重的增减。

重点是保证碰撞的几率小到比中大奖还小就可以了。

相关:

JaScript数组去重的几种方法分享

PHP实现数组去重的方法代码

JS简单实现数组去重的方法分析

JaScript数组去重的几种方法分享

数组去重,一般需求是给你一个数组,调用去重方法,返回数值副本,副本中没有重复元素。一般来说,两个元素通过 === 比较返回 true 的视为相同元素,需要去重,所以,1 和 "1" 是不同的元素,1 和 new Number(1) 是不同的元素,{} 和 {} 是不同的元素(引用不同)。(当然如果需求认为 {} 和 {} 算作相同的元素,那么解法就不一样了),本文主要和大家分享JaScript数组去重的几种方法。

method 1

使用两重循环

function unique(arr) {

var res = [];

for(var i = 0, len = arr.length;i < len; i++) {

var item = arr[i];

for(var j = 0, jLen = res.length; j

if(item == res[j]) break;

}if(j == jLen) res.push(item);

}return res;

}method 2

function unique(arr) {

var ret = []

for (var i = 0; i < arr.length; i++) {

var item = arr[i]

if (ret.indexOf(item) === -1) {

ret.push(item)

}}

return ret

}这里判断可以使用一个语法糖

function unique(arr) {

var res = [];

for(var i = 0, len = arr.length;i < len; i++) {

var item = arr[i];

(res.indexOf(item) === -1) && res.push(item);

}return res;

}但是在低版本浏览器并没有 indexOf

var indexOf = [].indexOf ?

function(arr, item) {

return arr.indexOf(item)

} :

function indexOf(arr, item) {

for (var i = 0; i < arr.length; i++) {

if (arr[i] === item) {

return i

}}

return -1

}function unique(arr) {

var ret = []

for (var i = 0; i < arr.length; i++) {

var item = arr[i]

if (indexOf(ret, item) === -1) {

ret.push(item)

}}

return ret

}method3

使用两重循环的另外一种比较方式,前面是将原数组的元素和结果数组一一比较,下面我们可以将原数组的重复元素的一个元素放入数组中

function unique(arr) {

var ret = [];

var len = arr.length;

var isRepeat;

for(var i=0; i

isRepeat = false;

for(var j=i+1; j

if(arr[i] === arr[j]){

isRepeat = true;

break;

}}

if(!isRepeat){

ret.push(arr[i]);

}}

return ret;

}这里还有一个优化的版本

function unique(a) {

var res = [];

for (var i = 0, len = a.length; i < len; i++) {

for (var j = i + 1; j < len; j++) {

// 这一步十分巧妙

// 如果发现相同元素

// 则 i 自增进入下一个循环比较

if (a[i] === a[j])

j = ++i; //j = i = i + 1;

}res.push(a[i]);

}return res;

}method4

用 jascript 中的 object 对象来当作 哈希表

function dedup(arr) {

var hashTable = {};

return arr.filter(function(value,index,arr){

var key = JSON.stringify(value);

var match = Boolean(hashTable[key]);

return (match ? false : hashTable[key] = true);

});

}因为 Object 的 key 值都是 String 类型,所以对于 1 和 "1" 无法分别,我们可以稍微改进下,将类型也存入 key 中

function dedup(arr) {

var ret = [];

var hash = {};

for(var i = 0; i < arr.length; i++) {

var item = arr[i];

var key = typeof(item) + item;

if(hash[key] !== 1) {

ret.push(item)

hash[key] = 1;

}}

return ret;

}

js数组去重常见的七种方法

直接给一个新的数组里面,利用es6的延展运算符

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。item是当前元素的值,index是当前元素的索引值。indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。利用indexOf() 查询到数组的下标,看是否等于当前的下标,相等的话就返回,否则不返回值。

5、借助新数组 通过 indexOf 方法判断当前元素在数组中的索引,如果与循环的下标相等则添加到新数组中

6、利用双重for循环

7、利用includes实现数组去重

以上就是比较常用的七种方法了,有不懂的留言吧。

利用jascript给数组去重的几种思路和实现代码汇总

1.遍历数组法

简单的去重方法,实现思路:新建一新数组,遍历传入数组,值不在新数组就加入该新数组中;注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写一些兼容低版本浏览器代码,源码如下: 2.对象键值对法

该方法执行的速度比其他任何方法都快, 就是占用的内存大一些,实现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,不是的话给对象新增该键并放入新数组。注意 点: 判断是否为js对象键时,会自动对传入的键执行“toString()”,不同的键可能会被误认为一样;例如: a[1]、a["1"] 。解决上述问题还是得调用“indexOf”。 3.数组下标判断法

还是得调用“indexOf”性能跟方法1不多,实现思路:如果当前数组的第i项在当前数组中次出现的位置不是i,那么表示第i项是重复的,忽略掉。否则存入结果数组。 4.排序后相邻去除法

虽然原生数组的”sort”方法排序结果不怎么靠谱,但在不注重顺序的去重里该缺点毫无影响。实现思路:给传入数组排序,排序后相同值相邻,然后遍历时新数组只加入不与前一值重复的值。 5.优化遍历数组法

该方法的实现代码相当酷炫,实现思路:获取没重复的右一值放入新数组。(检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断) 判断浏览器是否支持indexOf ,indexOf 为ecmaScript5新方法 IE8以下(包括IE8, IE8只支持部分ecma5)不支持

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

联系我们

工作日:9:30-18:30,节假日休息