JavaScript數組去重

數組去重是一個經典的面試問題,這裏記錄一下本身的心得和經常使用的處理方法。javascript

數字類型的數組去重&字符類型數組去重

對於數字類型數組 var arr = [1,2,3,4,3,2,1];去重或者對於字符類型數組 var arr = ['1','1','a','b','a'];去重java

使用Set去重

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過濾

indexOf能夠從前日後查找元素在數組中出現的索引位置,若是沒有找到就返回-1。因爲每次的都是從前日後找,當有兩個相同的值的時候,indexOf返回的是前一個值的,而當前索引必然大於indexOf直接返回,能夠根據二者是否相等來過濾數組元素。json

function use_filter(arr){
    return arr.filter(function(item,index,self){
        //從前日後查找對應元素的索引是否與當前索引相等,要是不相等說明以前出現太重複的元素
        return self.indexOf(item) === index;
    });
}
複製代碼

使用Object的鍵值對去重

使用一個臨時的對象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種數據類型均可能出如今數組中,此時的去重又變得不同了函數

數組中可能出現的數據類型

  • null
  • undefined
  • String
  • Number
  • Object
  • Boolean
  • Symbol 另外數組中的元素還多是數組、函數、日期、正則等其餘的特殊對象類型。 對於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
複製代碼

先嚐試用set去重

沒法對對象類型的數據進行去重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換成includes

indexOf的比較是 ===inclues的比較比indexOf改進的地方是可以判斷NaNdebug

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] ]
複製代碼

簡單的記錄一下本身的實驗結果,感受還可以改進,還在努力中。。。

相關文章
相關標籤/搜索