编写一个Javascript函数,传入一个数组,对数组中的元素进行去重并返回一个无重复元素的数组,数组的元素可以是数字、字符串、数组和对象。举例说明:
1. 如传入的数组元素为[123, "meili", "123", "mogu", 123],则输出:[123, "meili", "123", "mogu"]
2. 如传入的数组元素为[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],则输出:[123, [1, 2, 3], [1, "2", 3], "meili"]
3. 如传入的数组元素为[123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"],则输出:[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
把数组中的对象解析成字符串的方法用的是JSON.stringify()方法
var arr1 = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
var arr2 = [123, "meili", "123", "mogu", 123];
var arr3 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function unique(arr) {
var b = arr.map(item=>{
return JSON.stringify(item);//JSON.stringify(item)是把数组中的对象解析成字符串再比较
})
var c = Array.from(new Set(b));//Set(b)用来对b去重,但是去重后的结果不是我们想要的数组的形式,所以需要用 Array.from()的方法变成我们想要的数组的形式
var d = c.map(item=>{
return JSON.parse(item);
})
return d;
console.log(unique(arr1));
console.log(unique(arr2));
console.log(unique(arr3));
使用filter代替map,结果出来的结果不是想要的
注意:filter返回的是filter返回的是在一定条件下返回值为true的原数组项,所以此处最适合的是map或者for循环
所以如果需要从原数组中返回满足一定条件的数组,可以使用filter。
红宝书中是这样描述的:
相同点
不同点
Array.from
方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
类数组对象所谓类似数组的对象,本质特征只有一点,即必须有length
属性
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
关于call的思考
只要是部署了 Iterator 接口的数据结构,Array.from
都能将其转为数组。
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
补充:扩展运算符(...
)也可以将某些数据结构转为数组。扩展运算符背后调用的是遍历器接口(Symbol.iterator
),因此只要具有 Iterator 接口的对象,都可以使用扩展运算符。
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
上面代码中,querySelectorAll
方法返回的是一个NodeList
对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于NodeList
对象实现了 Iterator
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
const go = function*(){
yield 1;
yield 2;
yield 3;
};
[...go()] // [1, 2, 3]
上面代码中,变量go
是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。
const obj = {a: 1, b: 2};
let arr = [...obj]; // TypeError: Cannot spread non-iterable object
本身是数组的话
Array.from([1, 2, 3])
// [1, 2, 3]
作用类似于数组的
map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]
map
函数里面用到了this
关键字,还可以传入Array.from
的第三个参数,用来绑定this
。function countSymbols(string) {
return Array.from(string).length;
}
思想:通过拿出一个元素和剩下的元素依次比较,如果全部不相等则证明此元素为唯一
var arr1 = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
var arr3 = [123, "meili", "123", "mogu", 123];
var arr2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function unique(arr) {
let b=[]
for(let i=0;i<arr.length;i++){
let unexit=true
for(let j=i+1;j<arr.length;j++){
if(JSON.stringify(arr[i])===JSON.stringify(arr[j])){
unexit=false
break
}
else{
unexit=true
}
}
if(unexit){
b.push(arr[i])
}
}
return b
}
console.log(unique(arr1));
console.log(unique(arr2));
console.log(unique(arr3));
缺点:顺序会改变
var arr1 = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
var arr3 = [123, "meili", "123", "mogu", 123];
var arr2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function unique(arr) {
let b=[]
let hash={}
for(let i=0;i<arr.length;i++){
if(!hash[JSON.stringify(arr[i])]){
hash[JSON.stringify(arr[i])]=true
b.push(arr[i])
}
}
return b
}
console.log(unique(arr1));
console.log(unique(arr2));
console.log(unique(arr3));
这三种方法都可以实现对象去重,第二种存在一些缺点,顺序会改变。
参考:https://www.jb51.net/article/134411.htm
http://es6.ruanyifeng.com/#docs/set-map#Map
https://juejin.im/post/5ca7514a6fb9a05e790a46a4
原文:https://www.cnblogs.com/zhoujingguoguo/p/11539655.html