# 也谈面试必备问题之 JavaScript 数组去重

·  阅读 4614

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