# hanzichi/underscore-analysis

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

# JavaScript 数组去重 #9

Open
opened this Issue Jun 5, 2016 · 20 comments

Projects
None yet
Owner

# Why underscore

（觉得这部分眼熟的可以直接跳到下一段了...）

# 数组去重

### 方法一

```function unique(a) {
var res = [];

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

for (var j = 0, jLen = res.length; j < jLen; j++) {
if (res[j] === item)
break;
}

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

return res;
}

var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => [1, "1", "2"]```

```function unique(a) {
var res = [];

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

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

return res;
}

var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => [1, "1", "2"]```

```function unique(a) {

var res = a.filter(function(item, index, array) {
return array.indexOf(item) === index;
});

return res;
}

var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => [1, "1", "2"]```

### 方法二

```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;
}

res.push(a[i]);
}

return res;
}

var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => ["1", "2", 1]```

### 方法三（sort)

```function unique(a) {
return a.concat().sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
}

var a = [1, 1, 3, 2, 1, 2, 4];
var ans = unique(a);
console.log(ans); // => [1, 2, 3, 4]```

```var a = [1, 1, 3, 2, 1, 2, 4, '1'];
var ans = unique(a);
console.log(ans); // => [1, 2, 3, 4]```

### 方法四 （object）

```function unique(a) {
var seen = {};

return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}

var a = [1, 1, 3, 2, 1, 2, 4];
var ans = unique(a);
console.log(ans); // => [1, 3, 2, 4]```

```function unique(a) {
var ret = [];
var hash = {};

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

var key = typeof(item) + item;

if (hash[key] !== 1) {
ret.push(item);
hash[key] = 1;
}
}

return ret;
}

var a = [1, 1, 3, 2, '4', 1, 2, 4, '1'];
var ans = unique(a);
console.log(ans); // => [1, 3, 2, "4", 4, "1"]```

```var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];
var ans = unique(a);
console.log(ans); // => [Object, String]```

### 方法五 （ES6）

ES6 部署了 Set 以及 Array.from 方法，太强大了！如果浏览器支持，完全可以这样：

```function unique(a) {
return Array.from(new Set(a));
}

var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];
var ans = unique(a);
console.log(ans); // => [Object, Object, String, Number]```

# _.unique

```for (var i = 0, length = getLength(array); i < length; i++) {
var value = array[i],
// 如果指定了迭代函数
// 则对数组每一个元素进行迭代
computed = iteratee ? iteratee(value, i, array) : value;

// 如果是有序数组，则当前元素只需跟上一个元素对比即可
// 用 seen 变量保存上一个元素
if (isSorted) {
// 如果 i === 0，则直接 push
// 否则比较当前元素是否和前一个元素相等
if (!i || seen !== computed) result.push(value);
// seen 保存当前元素，供下一次对比
seen = computed;
} else if (iteratee) {
// 如果 seen[] 中没有 computed 这个元素值
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
}
} else if (!_.contains(result, value)) {
// 如果不用经过迭代函数计算，也就不用 seen[] 变量了
result.push(value);
}
}```

 学习了

 1024

 学习了

### Wangbaogang commented Oct 19, 2016

 赞赞赞 -- 来自点赞小能手

Open

### aleen42 commented Feb 20, 2017

 方法三如果用严格判定 item !== arr[pos - 1] 的话，不就能解决 Number 与 String 排在一起的问题咯？

### BigKongfuPanda commented Feb 23, 2017

 厉害，没想到有这么多种方法呢

### BigKongfuPanda commented Feb 23, 2017

 我想咨询一个问题，如果说数组是这样：arr = [{name:"tom"},{name:"tom"},{age: 18}]; 请问数组中的第一项和第二项，是算重复的嘛？ 如果是的话，你上面的方法好像失效了。

### aleen42 commented Feb 24, 2017

 @BigKongfuPanda 在作者看来，这种情况应该属于引用不同，因此不能称作完全相同的两个元素。这在于你如何理解两个元素何谓重复。

### BigKongfuPanda commented Feb 24, 2017

 嗯。严格意义上来说，如果比较地址的话，肯定是不同的。还是看实际情况下的要求吧。 发送自我的三星 Galaxy 智能手机。 -------- 原始信息 --------由： Aleen 日期: 17/2/24 17:25 (GMT+08:00) 收件人： hanzichi/underscore-analysis 抄送： BigKongfuPanda , Mention 主题： Re: [hanzichi/underscore-analysis] JavaScript 数组去重 (#9) @BigKongfuPanda 在作者看来，这种情况应该属于引用不同，因此不能称作完全相同的两个元素。这在于你如何理解两个元素何谓重复。 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread. {"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/hanzichi/underscore-analysis","title":"hanzichi/underscore-analysis","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/hanzichi/underscore-analysis"}},"updates":{"snippets":[{"icon":"PERSON","message":"@aleen42 in #9: @BigKongfuPanda 在作者看来，这种情况应该属于引用不同，因此不能称作完全相同的两个元素。这在于你如何理解两个元素何谓重复。"}],"action":{"name":"View Issue","url":"#9 (comment)"}}}

### tiansn commented Feb 27, 2017

 @hanzichi ,能分析下，每种方法的复杂度么，特别是最后的那几种

### zhangbowei commented Mar 1, 2017

 function unique(a) { return Array.from(new Set(a)); } var a = [{name: "hanzichi"}, {name: "hanzichi"},{age: 30}, new String(1), new Number(1)]; var ans = unique(a); console.log(JSON.stringify(ans)); //output [{"name":"hanzichi"},{"name":"hanzichi"},{"age":30},"1",1]

### JasonWilltrue commented Mar 8, 2017

 学习了
1 similar comment

 学习了

### CatBone commented Mar 15, 2017

 还一种简单的，可以运用es6的扩展运算符 `var unique = a => [...new Set(a)]` 😝😝😝

Open

### HowardTangHw commented Aug 15, 2017

 您好,我有个疑问,为什么在方法2中`j=++i`会把外部的循环中断掉,而不执行语句`res.push(a[i])`呢? ```function unique(a) { var res = []; for (var i = 0, len = a.length; i < len; i++) { for (var j = i + 1; j < len; j++) { if (a[i] === a[j]) { console.log('中断了') j = ++i; } } // 不清楚为啥j=++i;会break掉循环,不进入这一步 console.log('没被中断'); res.push(a[i]); } return res; } var a = [1, 1, "1", "2", 1]; var ans = unique(a); console.log(ans); // => ["1", "2", 1]```

Open

### Arvinzhu commented Sep 18, 2017

 @HowardTangHw 没有中断外部循环，而是内部循环在遇到充负的元素时，修改i的值，也就是修改外部循环下次循环的起点，当内部循环执行完毕后，push一个没有重复的值到res中，然后外部循环执行 以修改后的i值执行i++开始执行下一次循环

### seaskymonster commented Sep 20, 2017 • edited

 对于 1 和 "1" 无法分别这个问题： 其实可以在你的方法四上直接改 `function unique(a) { var seen = {}; return a.filter(function(item){ return seen.hasOwnProperty(typeof(item)+item) ? false: (seen[typeof(item)+item] = true); }) }`

### isLishude commented Sep 21, 2017

 indexOf 最大的问题就是 NaN 无法去重

### anotherleon commented Mar 28, 2018

 方法三： ` return !pos || item != ary[pos - 1];` 换成 ` return !pos || item !== ary[pos - 1];` 使用严格相等应该就行了吧

### Rabbitzzc referenced this issue Jul 10, 2018

Open

#### 数组取不相等的数 #28

to join this conversation on GitHub. Already have an account? Sign in to comment