數組去重是一個經典的面試問題,這裏記錄一下本身的心得和經常使用的處理方法。javascript
對於數字類型數組 var arr = [1,2,3,4,3,2,1];
去重或者對於字符類型數組 var arr = ['1','1','a','b','a'];
去重java
function use_set(arr){
return Array.from(new Set(arr));
}
複製代碼
1.先將原數組排序,數組會變成這樣 [1,1,2,2,3,3,4]
2.逐個的取出數組中的元素,加入另外一個臨時數組init
中,每次加入的時候判斷,若是init
爲空,或者init
的最後一個元素與當前要插入的不相等則插入 3.重複2的步驟直到遍歷完數組,完成後init
中保存的就是去重以後的數組元素面試
function reduce_sort(arr){
arr.sort(); //先排序
// 使用reduce挨個比較去重,去重後的結果保存在init數組中
return arr.reduce(function(init,current){
if(init.length === 0 || init[init.length-1]!=current){
init.push(current)
}
return init
},[]);
}
複製代碼
indexOf
能夠從前日後查找元素在數組中出現的索引位置,若是沒有找到就返回-1
。因爲每次的都是從前日後找,當有兩個相同的值的時候,indexOf
返回的是前一個值的,而當前索引必然大於indexOf
直接返回,能夠根據二者是否相等來過濾數組元素。json
function use_filter(arr){
return arr.filter(function(item,index,self){
//從前日後查找對應元素的索引是否與當前索引相等,要是不相等說明以前出現太重複的元素
return self.indexOf(item) === index;
});
}
複製代碼
使用一個臨時的對象obj
來記錄數組中的元素是否出現,其中將數組中的元素做爲鍵,出現了就記爲ture
。以後經過hasOwnProperty
來判斷是否包含這個屬性,包含就說明已經存在,不包含就添加爲obj
的新屬性。數組
function use_object(arr){
var obj = {};
return arr.filter(function(item){
return obj.hasOwnProperty(item) ? false : (obj[item] = true)
})
}
複製代碼
JavaScript中的數組存儲的數據類型是能夠不一樣的,也就是說JavaScript中的7種數據類型均可能出如今數組中,此時的去重又變得不同了函數
indexOf
在底層使用的方法是用===
進行判斷,下面是用===
判斷是否相等的例子,能夠發現有不少類型是不能直接用 ===
判斷的console.log(null === null); // true
console.log(undefined === undefined); // true
console.log('a' === 'a'); //true
console.log(String('a') === String('a')); // true
console.log(1 === 1); // true
console.log({} === {}); // false
console.log(true === true); // true
console.log(Symbol() === Symbol()); // false
console.log([] === []); // false
console.log(/a/ === /a/); //false
console.log(function(){console.log("1")} === function(){console.log("1")}); //false
console.log(NaN === NaN); // false
複製代碼
使用Object鍵值對去重的時候,須要轉成字符串,下面看一下幾個轉字符串的狀況測試
console.log(1..toString());//1
console.log('1'.toString());//1
console.log([1,function(){console.log("!")},NaN,undefined,null].toString());
//1,function(){console.log("!")},NaN,,
console.log({"a":1}.toString());//[object Object]
複製代碼
我只是嘗試了幾種類型,發現undefined和null在數組中的時候並不可以轉成字符串,獲取還存在其餘的狀況我沒有發現。下面再試試JSON.stringify()
序列化試試,發現也是有不少元素是不可以直接序列化爲字符串的,其餘JSON.stringify()的序列化問題參考blog.fundebug.com/2017/08/17/…ui
console.log(JSON.stringify([1,2,function(){console.log("1")},NaN,undefined,null]))
// [1,2,null,null,null,null
複製代碼
沒法對對象類型的數據進行去重spa
var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/,function(){console.log(1)},function(){console.log(1)}]
function use_set(arr){
return Array.from(new Set(arr));
}
console.log(use_set(arr));
/* [ 1, '1', 0, '0', undefined, null, NaN, {}, {}, [], [], /a/, /a/, [Function], [Function] ] */
複製代碼
indexOf
的比較是 ===
而inclues
的比較比indexOf
改進的地方是可以判斷NaN
debug
If Type(x) is different from Type(y), return false.
If Type(x) is Number, then
a. If x is NaN and y is NaN, return true.
b. If x is +0 and y is -0, return true.
c. If x is -0 and y is +0, return true.
d. If x is the same Number value as y, return true.
e. Return false.
Return SameValueNonNumber(x, y)
複製代碼
對於對象類型的使用JSON.stringify
序列化爲字符串,可是我沒有處理不能序列化的狀況,而後是用typeof+item
來代替item
避免出現1
和'1'
同時做爲key
的狀況
function func(arr){
var obj = {};
var res = arr.filter(function(item){
let key;
if(typeof(item)==="object"){
// 對於object使用JSON.stringify
key = JSON.stringify(item)
}else{
// 爲了不 1 和 '1' 這樣的狀況出如今同一個key中
key = typeof(item) + item;
}
return obj.hasOwnProperty(key) ? false : (obj[key] = true)
})
console.log(obj)
return res
}
複製代碼
測試用例
var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},{"a":1},{"a":1},[1,2],[1,2],/a/,/a/,function(){console.log(1)},function(){console.log(1)}]
複製代碼
測試結果
// 打印的輔助對象
{ number1: true,
string1: true,
number0: true,
string0: true,
undefinedundefined: true,
null: true,
numberNaN: true,
'{}': true,
'{"a":1}': true,
'[1,2]': true,
'functionfunction(){console.log(1)}': true }
// 打印結果
[ 1,
'1',
0,
'0',
undefined,
null,
NaN,
{},
{ a: 1 },
[ 1, 2 ],
[Function] ]
複製代碼
簡單的記錄一下本身的實驗結果,感受還可以改進,還在努力中。。。