第 113 题:根据以下要求,写一个数组去重函数
yygmind opened this issue · comments
-
如传入的数组元素为
[123, "meili", "123", "mogu", 123]
,则输出:[123, "meili", "123", "mogu"]
-
如传入的数组元素为
[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
,则输出:[123, [1, 2, 3], [1, "2", 3], "meili"]
-
如传入的数组元素为
[123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]
,则输出:[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
我不会🙁
用set做
 ̄□ ̄||
function parseArr(arr){
return [...new Set(arr.map(JSON.stringify))].map(JSON.parse)
}
没有考虑到数据类型为null,undefind等类型 包括数据为对象时key顺序不同的问题
这里再更正一下
// 判断对象
function isObj(obj){
return Object.prototype.toString.call(obj) === '[object Object]'
}
// 对象重整 对key进行排序
function parseObj(obj){
let keys = Object.keys(obj).sort()
let newObj = {}
for(let key of keys){
// 不晓得有没有有必要,反正把value为obj的情况也处理一下 - -
obj[key]=isObj(obj[key])?parseObj(obj[key]):obj[key]
newObj[key] = obj[key]
}
return newObj
}
// 最后
const arr = [1,'1',{a:1,b:"1"},{b:'1',a:1},{a:1,b:2},[1,2,3],null,undefined,undefined]
function passArr(arr){
return [...new Set(arr.map(item=>
isObj(item)? JSON.stringify(parseObj(item)) : ( !item ? item : JSON.stringify(item))
))].map(item=>!item?item : JSON.parse(item))
}
用set做的麻烦问一下怎么处理对象顺序不同的问题
如{a:1, b:2}和{b:2, a: 1}
NO Set
arr.map(JSON.stringify).filter((v, k, arr) => arr.indexOf(v) === k).map(JSON.parse)
用JSON.parse和JSON.stringify的同学,如果数组有undefined是不是就报错了;还有就是如果数组里包含循环引用的对象,是不是就都报错了╮(╯▽╰)╭
function dis(arr) {
const resObj = {};
const res = [];
arr.forEach((item) => {
const key = item + JSON.stringify(item);
if (!resObj[key]) {
res.push(item);
resObj[key] = item;
}
})
return res;
}
const test1 = [123, "meili", "123", "mogu", 123];
const test2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
const test3 = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili"];
console.log(dis(test1));
console.log(dis(test2));
console.log(dis(test3));
自定义哈希函数 哈希表
因为JSON.stringify碰到key顺序不同但值相同的对象时生成的字符串不一样,所以自定义哈希函数,处理对象时先把对象的key按字典序排序,然后再生成哈希字符串
function hash(arg) {
if (typeof arg === 'string') return `"${arg}"`
if (typeof arg === 'number' || typeof arg === 'undefined') return `${arg}`
if (typeof arg === 'symbol' || typeof arg === 'boolean') return arg.toString()
if (arg === null) return 'null'
if (Array.isArray(arg)) {
let res = '['
for (const item of arg) {
res += `${hash(item)},`
}
res += ']'
return res
}
let res = '{'
const keys = Object.keys(arg).sort()
for (const key of keys) {
res += `${key}:${hash(arg[key])},`
}
res += '}'
return res
}
function distinct(arr) {
const res = []
const map = {}
for (const item of arr) {
const key = hash(item)
if (!map[key]) {
map[key] = 1
res.push(item)
}
}
return res
}
var addSign = (data) => {
var signArr = data.map((o, i) => {
return JSON.stringify(o)
})
var set = [...new Set(signArr)]
return set.map((o, i) => JSON.parse(o))
}
//这个还要做类型判断和还原的,但是我们可以机智的用JSON.stringify它帮我们做了不同类型的处理
### 保留一下先,key顺序不同会出问题。不能是完全解决
案例测试:
addSign([123, "meili", "123", "mogu", 123]);
addSign([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]);
addSign([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]);
addSign([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: [1,2,{a:2222}]}}, "meili"]);
var $ = {
filters1: function(data) {
if (!data || !data.length) return [];
var temp = {0: [], 1: []};
for (var i = 0; i < data.length; i++) {
if (!~temp[0].indexOf(JSON.stringify(data[i]))) {
temp[0].push(JSON.stringify(data[i]))
temp[1].push(data[i]);
}
}
return temp[1];
},
filters2: function(data) {
if (!data || !data.length) return [];
var temp = {};
for (var i = 0; i < data.length; i++) {
temp[JSON.stringify(data[i])] = data[i];
}
return Object.values(temp);
},
filters3: function(data) {
if (!data || !data.length) return [];
var d = new Map();
for (var i = 0; i < data.length; i++) {
d.set(JSON.stringify(data[i]), data[i]);
}
var temp = [];
d.forEach(val => {
temp.push(val);
})
return temp;
},
filters4: function(data) {
if (!data || !data.length) return [];
return data.map(JSON.stringify).filter((v, k, data) => data.indexOf(v) === k).map(JSON.parse);
},
filters5: function(data) {
if (!data || !data.length) return [];
return [...new Set(data.map(JSON.stringify))].map(JSON.parse);
}
};
- 2 输出的顺序会不一致
- 4,5 数组里有 undefined 会报错
- 使用 JSON.stringify 只是为了保证唯一值来去重
- 其实不用 JSON.stringify 也可以实现,比如取 MD5
- 如果错误欢迎指正
let arr = [123, "meili", "123", "mogu", 123];
let _arr = [];
arr.forEach(it => {
if (!_arr.some(v => _.isEqual(v,it))) {
_arr.push(it);
}
});
console.log(_arr);
lodash
最原始(ben)的方式,两个for循环
var a=[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function fn(arr) {
let res =[];
arr.forEach(v=>{
if(res.length === 0){
res.push(v);
}else{
for(let i =0;i<=res.length;i++){
if(JSON.stringify(res[i]) === JSON.stringify(v))break;
if(i === res.length-1)res.push(v);
}
}
})
return res;
}
console.log(fn(a));//[123, [1, 2, 3], [1, "2", 3], "meili"]
var toType = (obj) => {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
var isEqual = (value, other) => {
var type = toType(value);
if (type !== toType(other)) return false;
if (type === 'number') {
return value === other
}
var valueLen = type === 'array' ? value.length : Object.keys(value).length;
var otherLen = type === 'array' ? other.length : Object.keys(other).length;
if (valueLen !== otherLen) return false;
if (type === 'array') {
for (var i = 0; i < valueLen; i++) {
if (!isEqual(value[i], other[i])) return false;
}
} else {
for (var key in value) {
if (value.hasOwnProperty(key)) {
if (!isEqual(value[key], other[key])) return false;
}
}
}
return true;
};
function unique(arr) {
arr = arr.reduce((previous, current) => {
var object = previous.filter(item => isEqual(item, current));
if (object.length === 0) {
previous.push(current);
}
return previous;
}, []);
return arr
}
unique([123, {a: 1}, {a: {c: 1, b: 1}}, {a: "1"}, {a: {b: 1, c: 1}}, "meili"])
// => [ 123, { a: 1 }, { a: { c: 1, b: 1 } }, { a: '1' }, 'meili' ]
function filterArray(array) {
var keys = {}
if (array && array.length) {
var rst = array.filter((val1)=>{
var str = JSON.stringify(val1);
if (!keys[str]) {
keys[str] = true;
return true;
} else {
return false;
}
})
}
return rst;
}
// [123, "meili", "123", "mogu", 123],则输出:[123, "meili", "123", "mogu"]
console.log(filterArray([123, "meili", "123", "mogu", 123]))
// [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],则输出:[123, [1, 2, 3], [1, "2", 3], "meili"]
console.log(filterArray([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]))
// [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"],则输出:[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
console.log(filterArray([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]))
function filterMap (arr) {
var Map103 = new Map()
arr.forEach(item => {
Map103.set(JSON.stringify(item), item)
})
return [...Map103.values()]
}
console.log(filterMap([123, "meili", "123", "mogu", 123]))
console.log(filterMap([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]))
console.log(filterMap([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]))
let x = [123, "meili", "123", "mogu", 123]
let x1 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
let x2 = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]
function func(arr) {
let newArr = arr.map(item => JSON.stringify(item))
return arr.filter((item,index)=>{
if(typeof item === 'object') {
return newArr.indexOf(JSON.stringify(item)) === index
}else{
return arr.indexOf(item) === index
}
})
}
console.log(func(x))
console.log(func(x1))
console.log(func(x2))
考点就在于2个一模一样对象的过滤,虽然是一样的,但是会作为不同的对象存储在堆内存中,所以需要用JSON.stringify 序列化才能准确判断,逻辑方面没有5楼写的好
let arr1 = [123, 'meili', '123', 'mogu', 123]
let arr2 = [123, [1, 2, 3], [1, '2', 3], [1, 2, 3], 'meili']
let arr3 = [
123,
{ a: 1 },
{ a: { b: 1 } },
{ a: '1' },
{ a: { b: 1 } },
'meili'
]
function repeat(arr) {
if (!Array.isArray(arr)) {
throw new TypeError('请输入数组···')
}
return [...new Set(arr.map(item => JSON.stringify(item)))].map(item =>
JSON.parse(item)
)
}
let res1 = repeat(arr1)
let res2 = repeat(arr2)
let res3 = repeat(arr3)
console.log(res1) //[123, "meili", "123", "mogu"]
console.log(res2) //[123, [1, 2, 3], [1, "2", 3], "meili"]
console.log(res3) //[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
const _toString = Object.prototype.toString;
const looseEqual = (a, b) => {
if (a === b) {
return true;
}
const typeA = _toString.call(a);
const typeB = _toString.call(b);
if (typeA === "[object Object]") {
if (typeB === "[object Object]") {
let flag = true;
for (let prop in a) {
if (a.hasOwnProperty(prop) && b.hasOwnProperty(prop)) {
flag = looseEqual(a[prop], b[prop]);
} else {
flag = false;
break;
}
}
return flag;
} else {
return false;
}
}
if (typeA === "[object Array]") {
if (typeB === "[object Array]") {
if (a.length !== b.length) {
return false;
}
let flag = true;
for (let i = 0; i < a.length; i++) {
if (!looseEqual(a[i], b[i])) {
flag = false;
break;
}
}
return flag;
} else {
return false;
}
}
// string number boolean undefined null, exclude regexp, date, symbol, set, map, weakMap, weakSet
return a === b;
};
const arr = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
const looseIncludes = (arr, item) => {
let flag = false;
for (let i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], item)) {
return flag = true;
}
}
return flag;
};
const result = arr.reduce((a, b) => {
if (looseIncludes(a, b)) {
return a;
}
return [...a, b];
},[]);
console.log(result);
function removal(arr){
let obj = {},key,newArr=[];
for(let i = 0;i<arr.length;i++){
key = JSON.stringify(arr[i]);
if(!obj[key]){
obj[key] = key;
newArr.push(JSON.parse(key));
}
}
return newArr
}
console.log(removal([123, "meili", "123", "mogu", 123])) //[123, "meili", "123", "mogu"]
console.log(removal([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"])) //[123, [1, 2, 3], [1, "2", 3], "meili"]
console.log(removal([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"])) //[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
先定义一个判断是否相同的函数,类型不同直接返回false,两边为object则递归再次比较
function isOne(left, right) {
if (typeof left !== typeof right) {
return false
}
if (typeof left == 'object') {
let isTrue = true
Object.keys(left).forEach(key => {
if (typeof left[key] == 'object') {
isTrue = isOne(left[key], right[key])
} else {
if (left[key] !== right[key]) {
isTrue = false
}
}
});
return isTrue
} else {
if (left === right)
return true
}
}
去重主函数:
function deepFliter(array) {
let result = []
for (let i = 0; i < array.length; i++) {
let temp = true
for (let j = i + 1; j < array.length; j++) {
if (isOne(array[j], array[i])) {
temp = false
}
}
if (temp) {
result.push(array[i])
}
}
return result
}
let array = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili"]
console.log(deepFliter(array))
没有什么数组去重是一个 new Set 解决不了的……等一下,你是说数组项里还可能有对象或数组?打扰了……
function removeRepeat(arr) {
const map = new Map();
// 先用 Set 过滤一波,过滤掉重复的基本类型
return [...new Set(arr)].filter(item => {
// 这里现在只剩下引用类型了
// 把引用类型转为 string,作为 Map 的键名
const key = JSON.stringify(item);
// 判断是否有此键名
if (!map.has(key)) {
map.set(key, true);
return true;
}
});
}
const test = [
{
it: [123, "meili", "123", "mogu", 123],
expect: [123, "meili", "123", "mogu"]
}, {
it: [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],
expect: [123, [1, 2, 3], [1, "2", 3], "meili"]
}, {
it: [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"],
expect: [123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
}
];
test.map(item => {
const result = removeRepeat(item.it);
const isPassed = JSON.stringify(result) === JSON.stringify(item.expect);
console.group(result);
isPassed ? console.log('%c√ Pass', 'color: green') :
console.log('%c× Failed', 'color: red');
console.groupEnd();
});
//false 不相等 true相等
function compareArray(t, j) {
if (t instanceof Array && j instanceof Array && t.length === j.length) {
let flag = true;
for (let i = 0; i < t.length; i++) {
flag = flag && t[i] === j[i];
if (!flag) {
break;
}
}
return flag;
}
}
//false 不相等 true相等
function compareObject(obj1, obj2) {
let retObj1 = {};
let retObj2 = {};
let flag = true;
transform(obj1, '', retObj1);
transform(obj2, '', retObj2);
for (let key in retObj1) {
if (retObj1[key] !== retObj2[key]) {
flag = false;
break;
}
}
return flag;
}
var transform = function (entry, str, temp) {
for (let key of Object.keys(entry)) {
if (typeof entry[key] === "object") {
transform(entry[key], str + key + '.', temp);
} else {
str += key;
temp[str] = entry[key];
}
}
}
function test(tmp) {
return Array.from(new Set(tmp)).reduce((prev, curr) => {
let flag = false
for (let t of prev) {
if (typeof t === 'object') {
if (curr instanceof Array) {
flag = !flag && compareArray(t, curr);
if (flag) {
break;
}
} else if (curr instanceof Object) {
flag = !flag && compareObject(t, curr)
if (flag) {
break;
}
}
}
}
if (!flag) {
prev.push(curr)
}
return prev
}, [])
}
大佬们给看下行不行呢?
function unique(arr) {
const result = [];
const isArray = Array.isArray;
for (let v of arr) {
result.every(e => !equal(v, e)) && result.push(v);
}
return result;
function equal(a, b) {
if (a && b && typeof a === 'object' && typeof b === 'object') {
return isArray(a) === isArray(b)
&& (isArray(a) ?
a.length === b.length && a.every((e, i) => equal(e, b[i]))
: Object.keys(a).length === Object.keys(b).length && Object.keys(a).every(k => equal(a[k], b[k]))
);
} else {
return a === b;
}
}
}
问题
问题实际上是一个去重问题,在 ===
的基础上新增如下两条规则:
- 规则1:如果是数组 则每个元素相等认为两个数组相等
- 规则2:如果是对象 则每个键的值都相等则认为两个对象相等
去重本身就是遍历数组比较而已,因此重点是实现含有以上两条扩展规则的比较函数。
实现比较函数思路:
- 判断函数中首先获取类型,若类型不等,则这两个值不相等,若类型相同,继续比较。
- 如果都为数组,遍历数组,比较每个成员,比较方法为当前方法。
- 如果都为对象,遍历对象键名,比较对应键值是否相等,比较方法为当前方法。
- 其他情况直接使用
===
比较。
去重思路:
- 对输入数组使用
reduce
方法遍历,传递初始累计值为[]
reduce
回调函数中对当前累计值使用some
方法检查当前元素是否存在,不存在则加入即可。- 完成
reduce
遍历后累计值即为去重后的数组。
代码实现
// 辅助函数 用于类型获取
var getType = (function() {
const class2type = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regexp', '[object Object]': 'object', '[object Error]': 'error', '[object Symbol]': 'symbol' };
return function getType(obj) {
if (obj == null) {
return obj + '';
}
const str = Object.prototype.toString.call(obj);
return typeof obj === 'object' || typeof obj === 'function' ? class2type[str] || 'object' : typeof obj;
};
})();
/**
* 判断两个元素是否相等
* 在 === 的基础上 有如下扩展规则
* 规则1:如果是数组 则每个元素相等认为两个数组相等
* 规则2:如果是对象 则每个键的值都相等则认为两个对象相等
* @param {any} target 比较元素
* @param {any} other 其他元素
* @returns {Boolean} 是否相等
*/
function isEqual(target, other) {
const t1 = getType(target);
const t2 = getType(other);
// 类型不同
if (t1 !== t2) return false;
if (t1 === 'array') {
if (target.length !== other.length) return false; // 数组长度不等
// 比较当前数组和另一个数组中的每个元素
return target.every((item, i) => {
// return item === target;
return isEqual(item, other[i]);
});
}
if (t2 === 'object') {
// 对象情况类似数组 但是遍历方法区别一下
const keysArr = Object.keys(target);
if (keysArr.length !== Object.keys(other).length) return false;
return keysArr.every(k => {
return isEqual(target[k], other[k]);
});
}
return target === other;
}
/**
* 对输入数组按照指定规则进行去重
*
* @param {Array<any>} arr 待去重的数组
* @returns {Array<any>} 去重后的新数组
*/
function unique(arr) {
return arr.reduce((outputArr, current) => {
const isUnique = !outputArr.some(item => isEqual(current, item));
if (isUnique) {
outputArr.push(current);
}
return outputArr;
}, []);
}
需要考虑交换key、复杂数据类型、环引用、symbol key
function flattern(o, path = '', res = {}) {
Object.keys(o).forEach((key) => {
if (typeof o[key] === 'object') {
flattern(o[key], `${path}.${key}`, res)
} else {
res[`${path}.${key}`.slice(1)] = o[key]
}
});
return res
}
function isObj(o) {
return Object.prototype.toString.call(o) === '[object Object]' || Array.isArray(o) || typeof o === 'function'
}
function deepEqual(a = {}, b = {}, cache = new Set()) {
if (typeof a === 'function') { // 解决函数
return a.toString() === b.toString()
}
if (cache.has(a)) { // 解决环引用
return a === b
}
cache.add(a)
const keys = Object.keys(a)
const symbolKeys = Object.getOwnPropertySymbols(a) // 解决symbol key
return (keys.length === Object.keys(b).length &&
symbolKeys.length === Object.getOwnPropertySymbols(b).length) &&
[...keys, ...symbolKeys].every(key => !isObj(a[key]) ?
a[key] === b[key] : deepEqual(a[key], b[key], cache))
}
function unique(arr) {
const cache = new Set() // 可以干掉NaN
const objCache = []
return arr.reduce((res, cur) => (
!isObj(cur) ? !cache.has(cur) && res.push(cur) && cache.add(cur)
: !objCache.find(o => deepEqual(o, cur)) && objCache.push(cur) && res.push(cur),
res
), []);
}
const arr = [123, "meili", "123", "mogu", 123],
arr1 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],
arr2 = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
function unique(arr){
const map = new Map()
const result = []
for (let i = 0; i < arr.length; i++) {
const key = typeof arr[i] + JSON.stringify(arr[i])
if (!map.get(key)) {
map.set(key, arr[i])
}
}
map.forEach(e => {
result.push(e)
})
return result
}
unique(arr) //[123, "meili", "123", "mogu"]
unique(arr1) // [123,[1,2,3],[1,"2",3],"meili"]
unique(arr2) //[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
function deEmphasis (arr = []){
let temp = [], temp1 = [];
arr.forEach(item => {
if(Array.isArray(item) || typeof item == 'object'){
item = JSON.stringify(item)
}
temp.push(item);
})
Array.from(new Set(temp)).forEach(obj =>{
try {
if(typeof obj === 'string' && (Array.isArray(JSON.parse(obj)) || typeof JSON.parse(obj) == 'object')){
temp1.push(JSON.parse(obj))
}else{
temp1.push((obj))
}
} catch (error) {
temp1.push((obj))
}
})
return temp1 ;
}
function dis(arr){
let resJsonArr = []
let resArr = []
arr.forEach(a=>{
let str = JSON.stringify(a)
if(resJsonArr.indexOf(str)==-1){
resJsonArr.push(str);
resArr.push(a);
}
})
return resArr;
}
function dis(arr){
let set = new Set();
let result = [];
arr.forEach(item=>{
let str = JSON.stringify(item)
if(!set.has(str)){
set.add(str)
result.push(item )
}
})
return result;
}
console.log(dis([123, {a: 1},null,null,undefined ,{a: {b: 1}}, {a: "1"}, "meili"]))
主要是增强了ES6中Map数据结构,使之键名可以辨别相同的对象和数组,可能有些冗余,可以看看.
let removeDuplicationArray = function(arr) {
let resultArr = [];
//增强Map
Map.prototype.ArrayList = [];
Map.prototype.hasArray = function(arr) {
if (this.ArrayList.length == 0) {
return false;
}
for (let i = 0; i < this.ArrayList.length; i++) {
let result = isEqualArray(arr, this.ArrayList[i]);
if (result == true) {
return true;
}
}
return false;
}
Map.prototype.setArray = function(arr) {
this.ArrayList.push(arr);
}
Map.prototype.ObjectList = [];
Map.prototype.hasObject = function(obj) {
for (let i = 0; i < this.ObjectList.length; i++) {
result = isEqualObject(this.ObjectList[i], obj);
if (result == true) {
return true;
}
}
return false;
}
//判断是否是同一个对象
function isEqualObject(obj1, obj2) {
if (Object.keys(obj1).length != Object.keys(obj2).length) {
return false;
}
for (const key in obj2) {
if (!(obj1.hasOwnProperty(key) && obj2.hasOwnProperty(key))) {
return false;
}
let itemType = Object.prototype.toString.call(obj2[key]).slice(8, -1);
switch (itemType) {
case "Object":
if (!isEqualObject(obj1[key], obj2[key])) {
return false;
}
break;
case "Array":
if (!isEqualArray(obj1[key], obj2[key])) {
return false;
}
break;
default:
if (obj1[key] !== obj2[key]) {
return false;
}
break;
}
}
return true;
}
Map.prototype.setObject = function(obj) {
this.ObjectList.push(obj);
}
//判断是否是同一个数组
function isEqualArray(arr1, arr2) {
if (arr1.length != arr2.length) {
return false;
}
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
}
//主函数开始
let hashTable = new Map();
let len = arr.length;
for (let i = 0; i < len; i++) {
let itemType = Object.prototype.toString.call(arr[i]).slice(8, -1);
switch (itemType) {
case "Array":
if (!hashTable.hasArray(arr[i])) {
hashTable.setArray(arr[i]);
resultArr.push(arr[i]);
}
break;
case "Object":
if (!hashTable.hasObject(arr[i])) {
hashTable.setObject(arr[i]);
resultArr.push(arr[i]);
}
break;
default:
if (!hashTable.has(arr[i])) {
hashTable.set(arr[i], arr[i]);
resultArr.push(arr[i]);
}
break;
}
}
return resultArr;
}
/* 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"] * / */
let x = [
[1, 2, 3],
[1, 2, 3, 4],
[1, 1, 2],
[1, 2, 3], { hobby: ["1", "2", "3"] },
{
hobby: ["1", "2", "3"]
},
{ hobby: ["1", "2"] }, { name: 'ibaiwei' }, { name: 'baiwei', sex: 'male' }, { name: 'baiwei', sex: 'male' }
];
console.log(removeDuplicationArray(x))
得到的结果
[ [ 1, 2, 3 ],
[ 1, 2, 3, 4 ],
[ 1, 1, 2 ],
{ hobby: [ '1', '2', '3' ] },
{ hobby: [ '1', '2' ] },
{ name: 'ibaiwei' },
{ name: 'baiwei', sex: 'male' } ]
function filter (arr) {
let hashObj = {};
let returnArr = [];
for (let val of arr) {
if (typeof val === 'object') {
let key = JSON.stringify(val);
if (!hashObj[key]) {
hashObj[key] = 1;
returnArr.push(val);
}
} else {
if (!returnArr.includes(val)) {
returnArr.push(val);
}
}
}
return returnArr;
}
实现起来代码略长,求简化
const s1 = new Set();
[123, "meili", "123", "mogu", 123].forEach(x => s1.add(x));
console.log(s1)
var arr = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function twoArrayIsEqual(arr1, arr2) {
if (!arr1 || !arr2) return false;
if (arr1.length !== arr2.length) return false;
for (let i=0; i<arr1.length; i++) {
if (Array.isArray(arr1[i]) && Array.isArray(arr2[i])) {
return twoArrayIsEqual(arr1[i], arr2[i])
}
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
for (let i=0; i<arr.length; i++) {
for (let j=i+1; j<=arr.length; j++) {
if (twoArrayIsEqual(arr[i], arr[j])) {
arr.splice(j, 1)
} else {
continue;
}
}
}
console.log(arr)
var arr = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
function twoObjectIsEqual(obj1, obj2) {
if (!obj1 || !obj2) return false;
if (typeof(obj1) == 'object' && typeof(obj2) == 'object') {
for (let i in obj1) {
if ((typeof(obj1[i]) == 'object') && (typeof(obj2[i]) == 'object')) {
return twoObjectIsEqual(obj1[i], obj2[i]);
}
if (obj1[i] !== obj2[i]) return false;
}
return true;
} else {
return false;
}
}
for (let i=0; i<arr.length; i++) {
for (let j=i+1; j<=arr.length; j++) {
if (twoObjectIsEqual(arr[i], arr[j])) {
arr.splice(j, 1)
} else {
continue;
}
}
}
console.log(arr)
就用Map加 JSON.stringify
function topic1 (arr) {
let newArr = arr.map(el => (typeof el === 'object' ? JSON.stringify(el) : el))
let arrSet = new Set(newArr).values()
return [...arrSet].map(el => {
try {
return JSON.parse(el)
} catch (err) {
return el
}
})
}
- 数据类型在掌控之内可以用 JSON.stringify & JSON.parse 方法
function removeDuplice1(arr) {
const arrCopy = arr.map(v => JSON.stringify(v))
const resultArr = [...new Set(arrCopy)].map(v => JSON.parse(v))
console.log(resultArr)
return resultArr
}
- 递归方法
const checkType = obj => Object.prototype.toString.call(obj)
function isEqual(a, b) {
if (checkType(a) !== checkType(b)) return false
// 基本类型情况,不包括边界情况如:function,Symbol
if (typeof a !== 'object') {
if (!Object.is(a, b)) return false
else return true
}
// 数组情况
if (Array.isArray(a)) {
if (a.length !== b.length) return false
else return a.every((v, index) => isEqual(a[index], b[index]))
}
// 对象情况
if (checkType(a) === "[object Object]") {
const arrA = Object.keys(a)
const arrB = Object.keys(b)
if (arrA.length !== arrB.length) return false
else return arrA.every((v, index) => isEqual(a[arrA[index]], b[arrB[index]]))
}
}
// 主函数
function removeDuplice(arr) {
const rArr = arr.concat()
for (let i=0; i<rArr.length; i++) {
for (let j=i+1; j<rArr.length; j++) {
if (isEqual(rArr[i], rArr[j])) {
rArr.splice(j, 1)
}
}
}
console.log(rArr)
return rArr
}
removeDuplice([123, "meili", "123", "mogu", 123])
removeDuplice([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"])
removeDuplice([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"])
function uniqueArray(arr) {
if (!arr || (typeof arr != 'object')) return
let newArr = [];
arr.forEach(item => {
var isExist = newArr.some(newItem => {
return compareObject(item, newItem);
});
if (!isExist) newArr.push(item)
// if (newArr.findIndex(value => value === item) == -1) {
// newArr.push(item)
// }
})
return newArr;
}
function compareObject(obj1, obj2) {
if (!obj1 instanceof Object || !obj2 instanceof Object) {
return obj1 === obj2
}
if (Object.keys.length !== Object.keys.length) return false;
for (var key in obj1) {
if (obj1[key] instanceof Object && obj2[key] instanceof Object) {
return compareObject(obj1[key], obj2[key])
} else {
if (obj1[key] !== obj2[key]) return false
}
}
return true;
}
_.uniqWith([123, "meili", "123", "mogu", 123], _.isEqual);
_.uniqWith([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"], _.isEqual);
_.uniqWith([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"], _.isEqual);
function fn(arr){
let map=new Map()
arr.forEach(element => {
if(!map.has(element)){
map.set(element,true)
}
});
let result=Array.from(map.keys())
console.log(result)
}
为啥你们的这么复杂 我感觉我的也没错啊
递归解决JSON.stringify(obj)的 key位置不同,重复添加
function removeSame(arr){
let hash = {}
//对象排序
return [... new Set(arr)].filter(item=>{
if(Object.prototype.toString.call(item) == '[object Object]'){
item = sortByKey(item)
}
let key = JSON.stringify(item)
if(hash[key]){
return false
}else{
hash[key] = item
return true
}
})
}
function sortByKey(obj){
if(typeof obj !== 'object'){
return obj
}
let cloneObj = obj instanceof Array ? []:{}
//进行一次排序,改变obj的当层顺序
obj = Object.keys(obj).sort().reduce((prev,curKey)=>{
prev[curKey] = obj[curKey];
return prev
},{})
//进入下一层遍历
Object.keys(obj).forEach(key=>{
cloneObj[key] = sortByKey(obj[key])
})
return cloneObj
}
function existEqualValue (arr, target) {
for(let i = 0, length = arr.length; i < length; i++) {
if (JSON.stringify(arr[i]) === JSON.stringify(target)) {
return true;
}
}
return false;
}
function unique (arr) {
return arr.reduce((accumulator, item) => {
if (typeof item === 'object') {
!existEqualValue(accumulator, item) && accumulator.push(item)
} else {
!accumulator.includes(item) && accumulator.push(item)
}
return accumulator;
}, []);
}
const removal = array =>
JSON.parse('['+
JSON.stringify(array)
.replace(/]|[|\s/g, '')
.split(',')
.filter((e, i, arr) => arr.indexOf(e) === i).join(',')
+']');
console.log(removal([123, 234, {a: 1}, {a: '1'}, {a: 1}, 123])) // [123, 234, {a: 1}, {a: '1'}]
-
function duplicateRemoval(arr) {
let s = new Set() // 用于记录去重后的成员,并去除重复非对象元素 let s2 = new Set() // 用于判断去除重复的对象和数组 let newArr = [] let newSize = s2.size for(let a of arr) { /** 如果元素是对象或者数组装换成字符串加入到s2集合中 如果s2成员变多,说明添加成功,这个元素此前没有重复元素,并将其添加到s集合 如果s2成员未变多,说明添加不成功该成员此前有重复元素,进行下一次循环 */ if(a instanceof Object) { s2.add(JSON.stringify(a)) if(s2.size !== newSize) { s.add(a) } newSize = s2.size } else { s.add(a) } } // 将s集合装换成数组返回 for(let k of s) { newArr.push(k) } return newArr }
var arr = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili","123",123,[1,2],[1,2],[1,2,3],[1,"2"],[2],{0:1,1:2}];
console.log(transform(arr));
function transform(arr){
const target = [];
//先做个基本类型的去重
arr = [...new Set(arr)];
arr.forEach(item=>{
if(!target.some(item1=>{
return isEqual(item,item1)
})){
target.push(item);
}
})
return target;
function isEqual(item,item1){
const type1 = Object.prototype.toString.call(item);
const type2 = Object.prototype.toString.call(item1);
//类型不匹配
if(type1!==type2){
return false;
}
if(["[object Object]","[object Array]"].includes(type1)){
const keys1 = Object.keys(item);
const keys2 = Object.keys(item1);
//键的数量不匹配
if(keys1.length!==keys2.length){
return false;
}
//某个键不相等
if(keys1.some((key,idx)=>{
return key!==keys2[idx]
})){
return false;
}
return keys1.every(key=>{
return isEqual(item[key],item1[key]);
})
}else{
return item === item1;
}
}
}
function test (arr) {
const map = {}
const result = []
arr.forEach((item, index) => {
let key = ''
if (typeof item === 'object') { // 用hash表来存储不重复内容,key只能为字符串
key = JSON.stringify(item)
} else {
key = String(item)
}
if (!map[key]) { // key值不同,存储
map[key] = [item] // 可能出现key值相同,内容不同,都要存进对应的键值中,例如123,'123'
result.push(item)
} else { // key值相同,判断内容是否相同
let nowArr = map[key]
let isSame = false
for (let i = 0; i < nowArr.length; i++) {
if (same(nowArr[i], item)) { // 如果内容相同,结束循环
isSame = true
break
}
}
if (!isSame) {
result.push(item)
map[key].push(item)
}
}
})
return result
}
function same (a, b) {
if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) { // 类型不同返回false
return false
}
if (typeof a !== 'object') { // 基本类型,直接判定为相同
return true
}
if (Object.prototype.toString.call(a) === '[object Array]') { // 数组循环递归判定
for (let i = 0; i < a.length; i++) { // 有一项不同结束循环
if (!same(a[i], b[i])) return false
}
return true
}
if (Object.prototype.toString.call(a) === '[object Object]') {// 对象循环递归判定
for (const key in a) { // 有一项不同结束循环
if (!same(a[key], b[key])) return false
}
return true
}
}
console.log(test([123, {a: 1}, {a: {b: 1}}, {a: '1'}, {a: {b: 1}}, 'meili']))得到结果
[ 123, { a: 1 }, { a: { b: 1 } }, { a: '1' }, 'meili' ]
// 获取数据类型
const getType = (data) =>
Object.prototype.toString
.call(data)
.replace(/^\[object\s(.+)\]$/, '$1')
.toLowerCase();
// 值是否相等
const isEqual = (a, b) => {
if (getType(a) !== getType(b)) return false;
if (getType(a) === 'array') {
return a.every((item, index) => {
return item === b[index];
});
}
if (getType(a) === 'object') {
return Object.keys(a).every((key) => {
return isEqual(a[key], b[key]);
});
}
return a === b;
};
const removeDuplicate = (arr) => {
if (getType(arr) !== 'array') {
throw '数据格式错误';
}
const newArr = [];
arr.forEach((outItem) => {
if (
!newArr.filter((innerItem) => {
return isEqual(outItem, innerItem);
}).length
) {
newArr.push(outItem);
}
});
return newArr;
};
console.log(
removeDuplicate([
1,
2,
3,
4,
{ a: 1 },
{ a: 1 },
{ a: 1 },
{ a: 1 },
{ a: { b: 1 } },
{ a: { b: 1 } },
{ a: { b: 1, d: { e: 1 } }, c: 1 },
{ a: { b: 1, c: 1, d: { e: 1 } } },
{ a: { b: 1, c: 1, d: { e: 2 } } },
{ a: { b: 1, d: { e: 2 }, c: 1 } },
{ a: { b: 1, d: { e: 2 }, c: 1 } },
1,
1,
2,
3,
5,
6,
7,
null,
null,
undefined,
'1',
'2',
'3',
]),
);
思路:递归比较
Array.equals =function(arr1,arr2){
if (arr1.length !== arr2.length) {
return false;
}
for (let index = 0; index < arr1.length; index++) {
if (!equals(arr1[index],arr2[index])) {
return false;
}
}
return true;
}
Object.equals=function(obj1,obj2){
const keys1= Object.keys(obj1).sort(); //避免键名顺序不一致导致的误判
const keys2 =Object.keys(obj2).sort();//避免键名顺序不一致导致的误判
if (!Array.equals(keys1,keys2)) {
return false;
}
for (const [index,item] of keys1.entries()) {
if (!equals(obj1[item],obj2[item])) {
return false;
}
}
return true;
}
function equals(obj1,obj2){
if (obj1 instanceof Object && obj2 instanceof Object) { // 两个都是引用类型
// 数组比较
if (Array.isArray(obj1) &&Array.isArray(obj2)) {
return Array.equals(obj1,obj2);
}else if (Array.isArray(obj1) || Array.isArray(obj2)) { // 数组和对象比较 false
return false;
}else{ //对象和对象比较
return Object.equals(obj1,obj2);
}
// 一个引用类型 一个基本类型 false
}else if(obj1 instanceof Object || obj2 instanceof Object)
{
return false;
}
else
{// 两个都是基本 类型 比较
return obj1 === obj2;
}
}
function indexOf(arr,obj){
for (const [index,item] of arr.entries()) {
if (equals(item,obj)) {
return index;
}
}
return -1;
}
// 去重逻辑
function distinct(arr){
const result =[];
arr.forEach(item=>{
if (indexOf(result,item) === -1) {
result.push(item);
}
})
return result;
}
console.log(distinct([1,2,[1,2,3],[{a:1,b:[6666,{f:123}]}],[{a:1,b:[6666,{f:123}]}] ]))
const isArray = Array.isArray;
function isObject(val) {
return val != null && typeof val === 'object' && Array.isArray(val) === false;
}
function isEqual(o1, o2) {
if(isArray(o1) && isArray(o2)){
if(o1.length !== o2.length){
return false;
}
for(let i=0;i<o1.length;i++){
if(o1[i] !== o2[i]){
return false
}
}
return true
}
else if(isObject(o1) && isObject(o2)){
const ks1 = Object.keys(o1).sort();
const ks2 = Object.keys(o2).sort();
if(ks1.length !== ks2.length){
return false;
}
if(!isEqual(ks1, ks2)){
return false;
}
for(let i=0;i<ks1.length;i++){
if( !isEqual(o1[ks1[i]] , o2[ks2[i]]) ){
return false
}
}
return true
}
return o1 === o2;
}
function unique(arr) {
const list = [];
//一直往列表里放 后面放的在列表里判断重复
for(let i=0;i<arr.length;i++){
const o1 = arr[i];
let same = false;
for(let j=0;j<list.length;j++){
const o2 = list[j];
if( isEqual(o1, o2) ){
same = true;
break;
}
}
if(!same){
list.push(o1);
}
}
return list;
}
// const o = [123, "meili", "123", "mogu", 123];
// const o = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
const o = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
console.log( unique(o) ) ;
wo ye bu hui
let clearRepeat = function (data) {
let newArr = [], params = {};
data.forEach((i) => { if (!params[i]) params[JSON.stringify(i)] = i; })
return Object.keys(params).map((i) => { return params[i] }) //返回结果
}
clearRepeat(arr);
Thank you
function setDELsame(arr,theArr=[]){
const isType= val =>Object.prototype.toString.call(val).slice(8,-1)
let newArr = arr.map((item,i)=>{
if(isType(item) === 'Object' || isType(item) === 'Array'){
return JSON.stringify(item)
}
return item
} )
while(newArr.length>0){
let value = newArr.shift()
let val = arr.shift()
theArr.push(val)
if(~newArr.indexOf(value)){
let index = newArr.indexOf(value)
newArr.splice(index,1)
arr.splice(index,1)
}
}
return theArr
}
let arr = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"];
function go(arr){
let res1 = arr.filter(function (val) {
return typeof val !== 'object';
})
res1 = Array.from(new Set([...res1]));
let res2 = arr.filter(function (val) {
return typeof val === 'object';
})
res2 = res2.map(function (val) {
return JSON.stringify(val);
})
res2 = Array.from(new Set([...res2]));
res2 = res2.map(function (val) {
return JSON.parse(val);
})
let res = res1.concat(res2);
return res;
}
console.log(go(arr))
//就是有点繁琐
ES6 写法
function unique(arr) {
return Array.from(new Set(arr.map(JSON.stringify))).map(JSON.parse)
}
参考了大家的JSON.stringify
function getUnrepeatArr(arr){
let obj = {}
return arr.filter((item) => {
return obj.hasOwnProperty(JSON.stringify(item)) ? false : (obj[JSON.stringify(item)] = true)
})
}
测试了三个用例,可以输出正确结果。
/*
第 113 题:编程题,根据以下要求,写一个数组去重函数(蘑菇街)
如传入的数组元素为[123, "meili", "123", "mogu", 123],则输出:[123, "meili", "123", "mogu"]
如传入的数组元素为[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],则输出:[123, [1, 2, 3], [1, "2", 3], "meili"]
如传入的数组元素为[123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"],则输出:[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
*/
function unique(arr) {
const res = [];
const isObject = item =>
Object.prototype.toString.call(item) === "[object Object]";
const isArray = item =>
Object.prototype.toString.call(item) === "[object Array]";
const compare = (a, b) => {
if (isArray(a) && isArray(b) && a.length === b.length) {
for (let i = 0; i < a.length; i++) {
if (!compare(a[i], b[i])) {
return false;
}
}
return true;
} else if (isObject(a) && isObject(b)) {
if (Object.values(a).length === Object.values(b).length) {
for (let key in a) {
if (!compare(a[key], b[key])) {
return false;
}
}
return true;
} else {
return false;
}
} else {
if (a === b) {
return true;
}
return false;
}
};
const find = function(res, item) {
if(res.length==0){
return false;
}
for (let i = 0; i < res.length; i++) {
if (compare(res[i], item)) {
return true;
}
}
return false;
};
for (let i = 0; i < arr.length; i++) {
if (!find(res, arr[i])) {
res.push(arr[i]);
}
}
return res;
}
console.log(unique([123, "meili", "123", "mogu","123"]));
console.log(unique([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]));
console.log(unique([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]));
function getArr(arr) {
let set = new Set()
let mArr = []
for(let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i]) || typeof (arr[i]) == 'object') {
let str = JSON.stringify(arr[i])
if (!mArr.includes(str)) {
set.add(arr[i])
mArr.push(str)
}
} else {
set.add(arr[i])
}
}
return [...set]
}
function isObject(value){
return Object.prototype.toString.call(value) === '[object Object]';
}
function isEqual (t1,t2) {
let arr = Object.entries(t1);
let res = true;
if(arr.length !== Object.keys(t2).length){
return false
}
arr.forEach(item=>{
let i = item[0];
let v = item[1];
if(
(Array.isArray(v) && Array.isArray(t2[i])) ||
(isObject(v) && isObject(t2[i]))
){
res = equalArray(v,t2[i])
}else{
v !== t2[i] && (res = false)
}
})
return res;
}
function deWeight(arr){
let res = [];
for(let i = 0;i<arr.length;i++){
if(Array.isArray(arr[i]) || isObject(arr[i])){
res.every(item=>{
return !isEqual(item,arr[i])
}) && res.push(arr[i])
}else{
res.indexOf(arr[i]) === -1 && res.push(arr[i])
}
}
return res
}
function dedup(list = []) {
let m = new Map()
Array.from(new Set(list)).map(item => {
if (typeof(item) === 'object') {
if (!m.has(JSON.stringify(item))) {
m.set(JSON.stringify(item), item)
}
} else {
m.set(item, item)
}
})
return [...m.values()]
}
dedup([123, "meili", "123", "mogu", 123])
dedup([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"])
dedup([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"])
对象转化为数组格式排序后,再用JSON.stringify处理,解决键名顺序问题
const arr1 = [123, "meili", "123", "mogu", 123];
const arr2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
const arr3 = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili", { a: { b: 1, c: 2, d: 4 } }, { a: { d: 4, c: 2, b: 1 } }];
const arr4 = [{ b: 1, c: 2 }, { c: 2, b: 1 }];
const cutRepeatNotype = (arr) => {
const getArray = (data) => {
if (data instanceof Array) {
let val = [];
for (let i = 0; i < data.length; i++) {
val.push(getArray(data[i]));
}
return val;
}
else if (data && typeof data === 'object') {
let val = [];
let map = new Map();
for (let k in data) {
map.set(k, data[k]);
}
([...map.keys()]).sort((a, b) => a > b ? 1 : -1).forEach(k => {
val.push([k, getArray(map.get(k))]);
});
return val;
}
else {
return data;
}
};
let arrStr = arr.map(item => ({
val: item,
type: JSON.stringify(getArray(item))
}));
let map = new Map();
return arrStr.filter(item => !map.has(item.type) && map.set(item.type, item.val)).map(item => item.val);
};
console.log(cutRepeatNotype(arr1));
console.log(cutRepeatNotype(arr2));
console.log(cutRepeatNotype(arr3));
console.log(cutRepeatNotype(arr4));
function delRepeat(originalArr) {
let arr = originalArr.slice(0)
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (objDeepEqual(arr[i], arr[j])) {
arr.splice(j, 1)
}
}
}
return arr
}
function objDeepEqual(source, target) {
if (typeof source !== typeof target) return false
if (typeof source === 'object') {
for (let key in source) {
if (typeof source[key] !== 'object') {
if (source[key] !== target[key]) {
return false
}
} else if (!objDeepEqual(source[key], target[key])) {
return false
}
}
} else if (source !== target) {
return false
}
return true
}
最笨的方法:
function d(arr) {
const len = arr.length;
let myArr = [];
for (let i = 0; i < len; i++) {
myArr[i] = JSON.stringify(arr[i])
}
let newArr = [];
for (let i = 0; i < len; i++) {
if (!newArr.includes(myArr[i])) {
newArr.push(myArr[i])
}
}
for (let i = 0; i < newArr.length; i++) {
newArr[i] = JSON.parse(newArr[i])
}
return newArr
}
数组里面还包含引用传递的对象没有管
function equal (source, target) {
var to = Object.prototype.toString
var q1 = to.call(source)
var q2 = to.call(target)
if (q1 === '[object Array]' && q2 === '[object Array]') {
return source.every((item, index) => item === target[index])
} else if (q1 === '[object Object]' && q2 === '[object Object]') {
for (var k in source) {
var item = source[k]
var t = target[k]
if (to.call(item) === '[object Object]' && to.call(t) === '[object Object]') {
return equal(item, t)
}
if (item !== t) {
return false
}
}
return true
} else {
return source === target
}
}
function start (a1) {
var result = [].concat(a1), r = []
while (result.length) {
var item = result.shift()
r.push(item)
for (var i = result.length - 1; i >= 0; i--) {
if (equal(item, result[i])) {
result.splice(i, 1)
}
}
}
return r
}
写的比较麻烦...
var arr1 = [123, "meili", "123", "mogu", 123];
var arr2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
var arr3 = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili"];
var arr4 = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili", [1, 2, 3], [1, "2", 3], [1, 2, 3]];
function unique(arr) {
var arrSet = [... new Set(arr)];
var arr = [];
var obj = [];
arrSet.map((item, index) => {
type(item, index, arr, obj);
});
if (arr.length > 0) {
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) { // 通过对应的角标删除arrSet对应的项
var index1 = arr[i];
var index2 = arr[j];
if (JSON.stringify(arrSet[index1]) === JSON.stringify(arrSet[index2])) {
arrSet.splice(index2, 1);
}
}
}
}
if (obj.length > 0) {
for (var i = 0; i < obj.length - 1; i++) {
for (var j = i + 1; j < obj.length; j++) {
var index1 = obj[i];
var index2 = obj[j];
if (JSON.stringify(arrSet[index1]) === JSON.stringify(arrSet[index2])) {
arrSet.splice(index2, 1);
}
}
}
}
return arrSet;
}
function type(item, index, arr, obj) {
if (item instanceof Object) {
if (Array.isArray(item)) {
arr.push(index); // 如果是数组,把对应的角标传入arr
} else {
obj.push(index); // 如果是对象,把对应的角标传入obj
}
}
}
console.log(unique(arr4));
function diff(arr){
let res = {};
let _arr = [];
for(let i = 0; i < arr.length; i++){
let key = typeof arr[i] + JSON.stringify(arr[i]);
if(!res[key]){
res[key] = true;
_arr.push(arr[i])
}
}
return _arr
}
let arr1 = [123, "meili", "123", "mogu", 123];
let arr2 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
let arr3 = [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili"]
console.log(diff(arr1))
console.log(diff(arr2))
console.log(diff(arr3))
function f(arr){
return [...new Set(arr.map(el=>JSON.stringify(el)))].map(el=>JSON.parse(el))
}
触及到老夫的知识盲区了
const uniq = (arr = []) => arr.reduce((t, c) => (t.includes(c) ? t : t.push(c), t), [])
const uniqArr = [123, "meili", "123", "mogu", 123]
console.log(uniq(uniqArr)) // [[123, "meili", "123", "mogu"]
//下面的不会,哈哈哈哈
function equals(a, b) {
if (a === b) return true
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b
if (a.prototype !== b.prototype) return false
const keys = Object.keys(a)
if (keys.length !== Object.keys(b).length) return false
return keys.every(k => equals(a[k], b[k]))
}
function removeRepeat(arr) {
return arr.reduce((acc, item) => {
if (!acc.find(a => equals(a, item))) {
acc.push(item)
}
return acc
}, [])
}
removeRepeat([123, 'meili', '123', 'mogu', 123])
function getType(data) {
return Object.prototype.toString.call(data)
}
function ff(arr) {
let targetArr = Array.from(new Set(arr))
let obj = {}
arr.forEach((item, index) => {
let typeStr = getType(item)
if (typeStr === '[object Object]' || typeStr === '[object Array]') {
let valStr = JSON.stringify(item)
if (obj[valStr]) {
targetArr.splice(index, 1)
} else {
obj[valStr] = true
}
}
})
return targetArr
}
ff([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"])
应该可以... 大概
如果 [1,2,3] 和 [1,3,2] 。{a:1,b:2} 和 {b:2,a:1} 也算相等的话
function unique(array) {
var newArr = [array[0]]
var len = array.length
for (var i = 0; i < len; i++) {
for (var j = 0; j < newArr.length; j++) {
if (isEq(newArr[j], array[i])) {
break
}
if (j == newArr.length - 1) {
newArr.push(array[i])
}
}
}
function isEq(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
var aLen = a.length
var bLen = b.length
if (aLen !== bLen) {
return false
}
for (var i = 0; i < aLen; i++) {
if (!b.includes(a[i])) {
return false
}
}
return true
} else if (typeof a == 'object' && typeof b == 'object') {
for (const key in a) {
if (a.hasOwnProperty(key)) {
return isEq(a[key], b[key])
}
}
} else {
return Object.is(a, b)
}
}
return newArr
}
不用搞的这么复杂吧, 上面这么多循环
var arr = [1, -1, 0, 0, 0, 123, [1, 2, 3], [1, '2', 3], [1, 2, 3], 'meili', null, '', null, '', NaN, NaN, undefined, undefined]
// arr = [123, "meili", "123", "mogu", 123]
// arr = [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]
function moveSame(arr) {
const map = {}
const result = []
for (let i = 0, len = arr.length; i < len; i++) {
const item = arr[i]
let key
if (typeof item === 'object') {
key = JSON.stringify(arr[i])
} else {
key = item + typeof item
}
if (!map[key]) {
map[key] = true
result.push(item)
}
}
return result
}
console.log(moveSame(arr));
用JSON.parse和JSON.stringify的同学,如果数组有undefined是不是就报错了;还有就是如果数组里包含循环引用的对象,是不是就都报错了╮(╯▽╰)╭
考虑的不错, 不过题目显然不是这个意思,而且数组是undefined 也不会报错, 会变成null值,如果非要这么搞, 那么就对数组或者对象的值先做针对处理,再用stringify。
引用对象确实是个应该考虑的事情, 不过这样子联想下去,那问题就太多了。 满足 1 2 3 三个条件,算法复杂度过得去就算吧。毕竟测试用例就这三个
一个for循环搞定
function filter(arr) {
let map = {};
let result = [];
for (let i = 0; i < arr.length; i++) {
console.log(JSON.stringify(arr[i]))
if (!map[JSON.stringify(arr[i])]) {
map[JSON.stringify(arr[i])] = true;
result.push(arr[i]);
}
}
return result;
}
使用一个对象来保存已有的数据。
var arr = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"];
function test(input) {
var t = input.reduce(function (acc, item){
acc[JSON.stringify(item)] = item;
return acc;
}, {});
return Object.keys(t).map(k => t[k])
}
console.log(test(arr))
const find10 = () => {
let arr55 = [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
let obj = {}
arr55.forEach(item => {
if (!obj[JSON.stringify(item)]) {
obj[JSON.stringify(item)] = item
}
})
let list = Object.values(obj)
}
find10()
function transform(arr) {
const set = new Set(arr.map(itm => itm !== void 0 ? JSON.stringify(itm) : void 0));
return Array.from(set).map(itm => {
if (itm === void 0) return void 0;
const parsed = JSON.parse(itm);
return typeof parsed !== 'object' ? JSON.parse(itm) : parsed;
})
}
console.log(
transform(
// [123, "meili", "123", "mogu", 123]
// [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
// [123, { a: 1 }, { a: { b: 1 } }, { a: "1" }, { a: { b: 1 } }, "meili"]
[123, { a: 1 }, { a: { b: 1 } }, undefined, { a: "1" }, { a: { b: 1 } }, "meili", null]
)
);
考虑对象的key值顺序,稍微麻烦了点
function deleteMul(arr) {
let set = new Set(arr);
arr = Array.from(set);
const is = (target) => Object.prototype.toString.call(target);
let objSet = [],
arrSet = [];
for (const iterator of arr) {
switch (is(iterator)) {
case "[object Object]":
objSet.push(iterator);
set.delete(iterator);
break;
case "[object Array]":
arrSet.push(iterator);
set.delete(iterator);
break;
default:
break;
}
}
const isSameObj = (a, b) => {
const aKeys = Object.keys(a),
bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) return false;
aKeys.sort((_a, _b) => _a - _b);
bKeys.sort((_a, _b) => _a - _b);
let i = 0;
while (i < aKeys.length) {
const aK = aKeys[i],
bK = bKeys[i];
if (aK !== bK) {
return false;
} else {
if (a[aK] !== b[bK]) {
const aType = is(a[aK]),
bType = is(b[bK]);
if (aType !== bType) return false;
switch (aType) {
case "[object Object]":
if (!isSameObj(a[aK], b[bK])) return false;
break;
case "[object Array]":
if (!isSameArr((a[aK], b[bK]))) return false;
break;
default:
return false;
}
}
}
i++;
}
return true;
};
const isSameArr = (a, b) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] === b[i]) {
continue;
} else {
const aType = is(a),
bType = is(b);
if (aType !== bType) return false;
switch (aType) {
case "[object Object]":
if (!isSameObj(a[i], b[i])) return false;
break;
case "[object Array]":
if (!isSameArr((a[i], b[i]))) return false;
break;
default:
return false;
}
}
}
return true;
};
let repeatSet = new Set();
for (let i = 0; i < objSet.length - 1; i++) {
if (repeatSet.has(i)) continue;
for (let j = i + 1; j < objSet.length; j++) {
if (repeatSet.has(j)) continue;
if (isSameObj(objSet[i], objSet[j])) {
repeatSet.add(j);
}
}
}
Array.from(repeatSet).forEach((i) => (objSet[i] = null));
repeatSet.clear();
for (let i = 0; i < arrSet.length - 1; i++) {
if (repeatSet.has(i)) continue;
for (let j = i + 1; j < arrSet.length; j++) {
if (repeatSet.has(j)) continue;
if (isSameArr(objSet[i], objSet[j])) {
repeatSet.add(j);
}
}
}
Array.from(repeatSet).forEach((i) => (arrSet[i] = null));
return Array.from(set)
.concat(objSet.filter((i) => i !== null))
.concat(arrSet.filter((i) => i !== null));
}
如果数组中都是都是基本数据类型,那么可以使用
function solution(arr){
return Array.from(new Set(arr))
}
现在是数组中的元素可能是引用数据类型,如对象,数组等,为此可以使用Set集合,Set中有的就跳过,没有就插入新数组
function solution(arr){
const hashSet=new Set();
const res=[];
for(const i of arr){
if(hashSet.has(JSON.stringify(i))){
continue;
}
hashSet.add(JSON.stringify(i));
res.push(i)
}
return res;
}
// let arr=[123, "meili", "123", "mogu", 123];
// let arr=[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]
// let arr=[123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]
// let arr=[1,'1',{a:1,b:"1"},{b:'1',a:1},{a:1,b:2},[1,2,3],null,undefined,undefined];
console.log(solution(arr))
let arr=[123, {a: 1,b:2},{b:2,a:1} , {a: "1"} , "meili"]对于该示例,如果判定{a:1,b:2}与{b:2,a:1}相等的话,那么上面的方法暂时不能排除,需要对对象类型进一步判断
就哈哈哈哈
function test(arr) {
let map = {};
let res = []
for (let i = 0; i < arr.length; i++) {
if (!map[JSON.stringify(arr[i])]) {
res.push(arr[i]);
map[JSON.stringify(arr[i])] = arr[i];
}
}
console.log(res);
}
test(arr)
const oUniq=arr=>arr.reduce((a,c,i,r)=>{if(typeof c ==='object'){!JSON.stringify(a).includes((JSON.stringify(c)))&&a.push(c) }else{!a.includes(c)&&a.push(c)};return a},[])
- 先把对象key排序
- 再用map去重
function removeDupObj(items) {
const map = new Map()
items.forEach(item => {
const keySortedObj = sortObjKeys(item)
map.set(JSON.stringify(keySortedObj), item)
})
return [...map.values()]
}
function sortObjKeys(obj) {
if (obj && typeof obj === 'object') {
// 数组或对象
const result = {}
Object.keys(obj).sort().forEach(k => {
result[k] = sortObjKeys(obj[k])
})
return result
} else {
return obj
}
}