数组去重有哪些方法?
- 利用
es6
中的Set
去重,将数组传入到Set
方法中就可以了 - 两层
for
循环+splice
,如果拿每个元素与后面元素进行对比,如果有相同就讲后面重复的元素用splice
删除掉 indexof
实现去重,创建一个空数组,然后遍历原数组,取出每个值,进行indexof
判断,如果等于-1
表示不存在,加入到新数组中。- 利用
sort
进行排序,,然后两两相邻比较,如果不相等就加入到新数组中 - 利用
includes
判断新数组中是否存在该元素,如果不存在就添加 - 利用
filter
如果找的那个元素的索引和遍历的当前索引一直,表示只有一个 ,则添加
纯数组去重
方法一:利用 ES6 Set 去重(ES6 中最常用)
function unique(arr) {
return Array.from(new Set(arr));
}
var arr1 = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, 0, 'a', {}, {}]
//{}没有去重
如果不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。
方法二:利用 for
嵌套 for
,然后 splice
去重(ES5 中最常用)
function unique(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [1, 2, 'true', 'b', 15, false, undefined, NaN, NaN, 'a', {}, {}]
//NaN和{}没有去重,2个null都去掉了
方法三:利用indexOf
去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log("type error!");
return;
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array.indexOf(arr[i]) === -1) {
array.push(arr[i]);
}
}
return array;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); //[1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, NaN, 0, 'a', {}, {}]
//NaN,{}没有去重
新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则 push 进数组。
方法四:利用sort()
function unique(arr) {
if (!Array.isArray(arr)) {
console.log("type error!");
return;
}
arr = arr.sort();
var array = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== arr[i - 1]) {
array.push(arr[i]);
}
}
return array;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); //[0, 1, 15, 2, NaN, NaN, {}, {}, 'a', 'b', false, null, 'true', true, undefined]
//NaN,{}没有去重
利用 sort()
排序方法,然后根据排序后的结果进行遍历及相邻元素比对。
方法五:利用对象的属性不能相同的特点进行去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log("type error!");
return;
}
var array = [];
var obj = {};
for (var i = 1; i < arr.length; i++) {
if (!obj[arr[i]]) {
array.push(arr[i]);
obj[arr[i]] = 1;
} else {
obj[arr[i]]++;
}
}
return array;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [2, 1, 'true', 'b', 15, false, undefined, null, NaN, 0, 'a', {}]
//2个true都去掉了,NaN,{}去重
方法六:利用includes
function unique(arr) {
if (!Array.isArray(arr)) {
console.log("type error!");
return;
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (!array.includes(arr[i])) {
//includes 检测数组是否有这个值
array.push(arr[i]);
}
}
return array;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); //[1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, 0, 'a', {}, {}]
//{}没有去重
方法七:利用hasOwnProperty
function unique(arr) {
var obj = {};
return arr.filter((item, index, arr) => {
return obj.hasOwnProperty(typeof item + item)
? false
: (obj[typeof item + item] = true);
});
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); //[1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, 0, 'a', {}]
//所有的都去重了
利用 hasOwnProperty
判断是否存在对象属性
扩展:hasOwnProperty()
语法:
obj.hasOwnProperty(prop)
,参数prop
为字符串
- js 原生方法,
object.prototype.hasOwnProperty()
- 返回值: 返回一个布尔值, 判断该对象是否含有指定属性, 不包含继承来的属性
var obj = new Object();
obj.prop = "wang";
obj.hasOwnProperty("prop"); //true
delete o.prop;
obj.hasOwnProperty("prop"); //false
方法八:利用filter
function unique(arr) {
var obj = {};
return arr.filter((item, index, arr) => {
return arr.indexOf(item, 0) === index;
});
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [1, 2, 'true', 'b', true, 15, false, undefined, null, 0, 'a', {}, {}]
//2个NaN都去掉了,{}没有去重
方法九:利用递归去重
只适合纯数字数组,不适合字符串数组
function unique(arr) {
var array = arr;
var len = array.length;
array.sort(function (a, b) {
//排序后更加方便去重
return a - b;
});
function loop(index) {
if (index >= 1) {
if (array[index] === array[index - 1]) {
array.splice(index, 1);
}
loop(index - 1); //递归loop,然后数组去重
}
}
loop(len - 1);
return array;
}
var arr1 = [
1,
2,
1,
"true",
"b",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
var arr2 = [1, 2, 1, 4, 5, 2];
console.log(unique(arr1)); // [1, 2, 'true', 'b', 'true', false, null, 0, true, 15, NaN, NaN, 'a', {}, {}, undefined]
console.log(unique(arr2)); //[1, 2, 4, 5]
方法十:利用Map
数据结构去重
function unique(arr) {
let map = new Map();
let array = new Array(); //数组用于返回结果
for (var i = 0; i < arr.length; i++) {
if (map.has(arr[i])) {
//如果有该key值
map.set(arr[i], true);
} else {
map.set(arr[i], false);
array.push(arr[i]);
}
}
return array;
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, 0, 'a', {}, {}]
//{}没有去重
创建一个空 Map
数据结构,遍历需要去重的数组,把数组的每一个元素作为 key
存到 Map
中。由于 Map
中不会出现相同的 key
值,所以最终得到的就是去重后的结果。
方法十一:利用reduce
+includes
function unique(arr) {
return arr.reduce(
(prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]),
[]
);
}
var arr = [
1,
2,
1,
"true",
"b",
"true",
true,
true,
15,
15,
false,
false,
undefined,
undefined,
null,
null,
NaN,
NaN,
0,
0,
"a",
"a",
{},
{},
];
console.log(unique(arr)); // [1, 2, 'true', 'b', true, 15, false, undefined, null, NaN, 0, 'a', {}, {}]
//{}没有去重
对象数组去重
方法一:对象访问属性
采用对象访问属性的方法,判断属性值是否存在,如果不存在就添加。
var arr = [
{
key: "01",
value: "乐乐",
},
{
key: "02",
value: "博博",
},
{
key: "03",
value: "淘淘",
},
{
key: "04",
value: "哈哈",
},
{
key: "01",
value: "乐乐",
},
];
// 方法1:利用对象访问属性的方法,判断对象中是否存在key
var result = [];
var obj = {};
for (var i = 0; i < arr.length; i++) {
if (!obj[arr[i].key]) {
result.push(arr[i]);
obj[arr[i].key] = true;
}
}
console.log(result); // [{key: "01", value: "乐乐"},{key: "02", value: "博博"},{key: "03", value: "淘淘"},{key: "04", value: "哈哈"}]
方法二:reduce
方法
采用数组中的 reduce
方法,遍历数组,也是通过对象访问属性的方法
// 方法2:利用reduce方法遍历数组,reduce第一个参数是遍历需要执行的函数,第二个参数是item的初始值
var obj = {};
arr = arr.reduce(function (item, next) {
obj[next.key] ? "" : (obj[next.key] = true && item.push(next));
return item;
}, []);
console.log(arr); // [{key: "01", value: "乐乐"},{key: "02", value: "博博"},{key: "03", value: "淘淘"},{key: "04", value: "哈哈"}]
两个对象数组去重
方法一:filter
+findIndex
方法
方法:
const uniqueArray = mergedArray.filter(
(item, index, self) => index === self.findIndex((t) => t.id === item.id)
);
工作原理:filter
方法会遍历 mergedArray
中的每一个元素。
对于每个元素,使用 findIndex
查找该元素在 mergedArray
中第一次出现的索引。
如果当前元素的索引与第一次出现的索引相同,则该元素是唯一的,会被保留在 uniqueArray
中。
性能:
这种方法的时间复杂度是 O(n^2),因为对于每个元素都要调用一次 findIndex
,这会导致在数组较大时性能下降。
优势:
这种方代码简洁性优先,数据规模较小(如 < 1000 项)或无需频繁调用。
该方法可匹配多个参数进行去重。
示例:
const array1 = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const array2 = [
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
const mergedArray = [...array1, ...array2];
const uniqueArray = mergedArray.filter(
(item, index, self) => index === self.findIndex((t) => t.id === item.id)
);
console.log(uniqueArray);
方法二:reduce
+some
方法
方法:
const uniqueArray = mergedArray.reduce((acc, item) => {
if (!acc.some((existingItem) => existingItem.id === item.id)) {
acc.push(item);
}
return acc;
}, []);
工作原理:reduce
方法会遍历 mergedArray
中的每一个元素,并将结果累积到 acc
(累加器)中。
对于每个元素,使用 some
方法检查 acc
中是否已经存在具有相同 id
的元素。
如果不存在,则将当前元素添加到 acc
中。
性能:
这种方法的时间复杂度也是 O(n^2),因为对于每个元素都要调用一次 some
,但在某些情况下,它可能会比 filter
和 findIndex
方法更高效,尤其是当数组较大且重复元素较少时。
优势:
需要显式控制累积过程(如添加额外逻辑),或需与其他 reduce
操作结合使用。
该方法可匹配多个参数进行去重。
示例:
const array1 = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const array2 = [
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
const mergedArray = [...array1, ...array2];
const uniqueArray = mergedArray.reduce((acc, item) => {
if (!acc.some((existingItem) => existingItem.id === item.id)) {
acc.push(item);
}
return acc;
}, []);
console.log(uniqueArray);
方法三:使用 Map
或 Set
方法
通过 Map
存储已处理的 id
,时间复杂度降为 O(n):
方法:
const uniqueArray = [
...new Map(mergedArray.map((item) => [item.id, item])).values(),
];
由于把
id
作为Map
的key
,所以该方法不支持匹配多个参数进行去重。
示例:
const array1 = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const array2 = [
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
const mergedArray = [...array1, ...array2];
const uniqueArray = Array.from(
new Map(mergedArray.map((item) => [item.id, item])).values()
);
console.log(uniqueArray);
方法四:使用 lodash
库的 _.uniqBy
如果你在项目中使用了 Lodash
库,可以使用它的 uniqBy
方法来快速去重。
方法:
const _ = require("lodash");
const uniqueArray = _.uniqBy(mergedArray, "id");
该方法不支持匹配多个参数进行去重。
示例:
const _ = require("lodash");
const array1 = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const array2 = [
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
const mergedArray = [...array1, ...array2];
const uniqueArray = _.uniqBy(mergedArray, "id");
console.log(uniqueArray);
取出两个纯数组的不同元素
// 取出两个数组的不同元素
var arr1 = [0, 1, 2, 3, 4, 5];
var arr2 = [0, 4, 6, 1, 3, 9];
function getArrDifference(arr1, arr2) {
return arr1.concat(arr2).filter(function (v, i, arr) {
return arr.indexOf(v) === arr.lastIndexOf(v);
});
}
console.log(getArrDifference(arr1, arr2)); //输出:(4) [2, 5, 6, 9]
console.log(getArrDifference(arr2, arr1)); //输出:(4) [6, 9, 2, 5]
取出两个纯数组的不相同元素
var arr1 = [0, 1, 2, 3, 4, 5];
var arr2 = [0, 4, 6, 1, 3, 9];
function getArrEqual(arr1, arr2) {
let newArr = [];
for (let i = 0; i < arr2.length; i++) {
for (let j = 0; j < arr1.length; j++) {
if (arr1[j] === arr2[i]) {
newArr.push(arr1[j]);
}
}
}
return newArr;
}
console.log(getArrEqual(arr1, arr2)); //输出:(4) [0, 4, 1, 3]
console.log(getArrEqual(arr2, arr1)); //输出:(4) [0, 1, 3, 4]