js基本操做-數組去重

js基本操做-數組去重


寫在前面

JavaScript 數組去重常常出如今前端招聘的筆試題裏,好比:javascript

有數組 var arr = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0],請用 JavaScript 實現去重函數 unqiue,使得 unique(arr) 返回 ['a', 'b', 'c', '1', 0, 1, '']前端

做爲筆試題,考點有二:java

  • 正確。別小看這個考點,考慮到 JavaScript 常常要在瀏覽器上運行,在千姿百態的各類瀏覽器環境下要保障一個函數的正確性可不是一件簡單的事,不信你繼續讀完這篇博客。
  • 性能。雖然大部分狀況下JavaScript語言自己(狹義範疇,不包含DOM等延拓)不會致使性能問題,但很不幸這是一道考題,所以面試官們仍是會把性能做爲一個考點。

全部的方法都來自網上,學到了纔是本身的!!
而後,寫在前面,帶上咱們可愛的小夥伴。
小夥伴jquery

基本介紹

文章主要是對js數組去重的經常使用方法進行介紹。JS去重,看起來簡單,可是其實暗藏許多的小竅門。考的不單單是實現這個功能,更能看出你對計算機程序執行的深刻理解。下面將從數組去重的方法進行詳細的瞭解。es6

數組去重的方法

1.嵌套循環比較

兩層for循環,for循環中每次從原數組中取出一個元素,用這個元素循環與結果數組對比。若結果數組中沒有該元素,則存到結果數組中。面試

Array.prototype.unique_towFor = Array.prototype.unique_towFor || function(){
    var result = [];
    if(this.length <= 0) return result;
    result.push(this[0]);
    for(var i = 1; i < this.length; i++){
        var notIn = true;
        for(var j = 0; j < result.length; j++){
            if(this[i] == result[j]){
                notIn = false;
                break;
            }
        }
        if(notIn){
            result.push(this[i]);
        }
    }
    return result;
}

2.臨時數組保存

算法的基本思想,就是,把去重後的結果放在一個臨時數組中,對原來數組的元素與臨時數組元素比較,臨時數組中不存在這個元素的,放入臨時數組。算法

Array.prototype.unique_tempArray = Array.prototype.unique_tempArray || function(){
    var result = [];//臨時數組
    for(var i = 0; i < this.length; i++){
        if(result.indexOf(this[i]) == -1){
            result.push(this[i]);
        }
    }
    return result;
}

3.利用對象去重(基礎經常使用)

建立一個新的數組存放結果,和一個空對象。for循環時,每次取出一個元素與對象進行對比,若是這個元素不重複,則把它存放到結果數組中,同時把這個元素的內容做爲對象的一個屬性,並賦值,存入到對象中。這個方法用做統計也很方便。數組

Array.prototype.unique_objectArray = Array.prototype.unique_objectArray || function(){
    var result = [];
    var obj = {};
    for(var i = 0; i < this.length; i++){
        if(!obj[this[i]]){
            obj[this[i]] = 1;
            result.push(this[i]);
        }else{
            obj[this[i]] ++;
        }
    }
    return result;
}

4.先排序,後去重

先把數組排序,而後比較相鄰的兩個值。 排序的時候用的JS原生的sort方法,JS引擎內部用的是快速排序,此方法速度比較快!無語中。瀏覽器

Array.prototype.unique_sortArray = Array.prototype.unique_sortArray || function(){
    this.sort();
    var result = [this[0]];
    for(var i = 1; i < this.length; i++){
        if(this[i] !== result[result.length - 1] ){
            result.push(this[i]);
        }
    }
    return result;
}

5.利用ES6的Set對象和Array.from方法

  • [ ] Set對象能夠是任何類型的單個值的集合。它是ES6新增的有序列表集合,它不會包含重複項。以前咱們一般用對象(Object)或者數組(Array)來實現沒有重複項的集合。
  • [ ] Array.from()方法能夠將一個類數組對象或可遍歷對象轉換成真正的數組。
Array.prototype.unique_es6SetArray = Array.prototype.unique_esSetArray || function(){
    return Array.from(new Set(this));
}

6.利用filter和Map對象

  • [ ] filter()方法使用指定的函數測試全部元素,並建立一個包含全部經過測試的元素的新數組。
Array.prototype.unique_filterArray = Array.prototype.unique_filterArray || function(){
    return this.filter(function(item, index, arr){
        return arr.indexOf(item) === index;
    });
}

既然可使用filter的方法,那麼也可使用filter加object的方法,這裏使用Map對象。性能優化

Array.prototype.unique_es6MapArray = Array.prototype.unique_es6MapArray || function(){
    const seen = new Map();
    return this.filter(function(item, index, arr){
        !seen.has(item) && seen.set(item, 1);
    });
}

這裏的filter函數能夠簡化,固然也有人這樣寫

Array.prototype.unique_es6MapArray = Array.prototype.unique_es6MapArray || function(){
    const seen = new Map();
    return this.filter(
        (a) => !seen.has(a) && seen.set(a, 1)
    );
}

7.使用第三方

最後,可使用第三方庫函數jquery和underscore或者lodash
下面以lodash和underscore爲例

Array.prototype.unique_3partyArray = Array.prototype.unique_3partyArray || function(){
    return _.uniq(arr);//要先引入lodash.js或者underscore.js
}

其餘說明

  • 以上的全部方法,都來自網上。
  • 全部的方法,都必須腳踏實地,在具體應用場景下去分析、去選擇,咱們應該按照具體的狀況,來選擇方法。
  • 由於瀏覽器的多樣性,前端的應用場景常常很複雜,性能優化充滿挑戰,也充滿機遇。
  • 學會了纔是本身的,知道會用會寫,纔是咱們最終的目標。

方法中,建議參考underscore.js的源代碼的方法。如下是underscore.js中uniq的源碼。

// Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = cb(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = getLength(array); i < length; i++) {
      var value = array[i],
          computed = iteratee ? iteratee(value, i, array) : value;
      if (isSorted) {
        if (!i || seen !== computed) result.push(value);
        seen = computed;
      } else if (iteratee) {
        if (!_.contains(seen, computed)) {
          seen.push(computed);
          result.push(value);
        }
      } else if (!_.contains(result, value)) {
        result.push(value);
      }
    }
    return result;
  };

文檔說明以下:

uniq_.uniq(array, [isSorted], [iteratee]) Alias: unique

Produces a duplicate-free version of the array, using === to test object equality. In particular only the first occurence of each value is kept. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iteratee function.

_.uniq([1, 2, 1, 4, 1, 3]);

=> [1, 2, 4, 3]

本文僅只用於學習、研究和交流目的,我也是學習事後慢慢總結過來的,若是有什麼錯誤或者好的建議,歡迎你們批評指正!

相關文章
相關標籤/搜索