淺談Javascript數組去重

javascript 數組 array 去重 distinct uniquejavascript


恰好前天面試的時候面試官問到了數組去重的問題,當時有點語塞只想到用了兩個循環檢測(其實模模糊糊想到了hash的方法作可是因爲記得不清不敢說= =!),思路是檢測是否有元素重複,而後將只出現一次的元素推入到新數組中,而後返回新數組。而後面試官又問這種方法的時間效率,因而黑線了。so這兩天看了一下相關的文章,在這裏也總結一下javascript數組去重的方法。css

兩層循環檢測重複元素法

首先,介紹一下你們都會想到的兩層循環的demo,以下例:html

function distinct(arr) {
    var ret = [],
        length = arr.length;
    for(var i = 0;i < length; i++){
        for(j = i+1; j<length;j++){
            if(arr[i] === arr[j]){
                j = ++i;
            }
        }
        ret.push(arr[i]);
    }
    return ret;
}
var arra = [1,2,3,4,4,1,1,2,1,1,1];
distinct(arra);                              //返回[3,4,2,1]

<!--more-->
如上的代碼實現是輕鬆易得的,思路以下:java

  1. 首先外層循環比遍歷整個數組git

  2. 內層循環匹配是否有值重複程序員

    a.如判斷有相同元素則自增i變量,跳出i的循環
    b.如判斷無時則將無相等值的元素推入到ret數組中

    3.返回ret。github

優勢:便捷易懂,大多數程序員能想到。
缺點:很明顯時間消耗過高,兩層循環時間消耗太多,時間的消耗爲O(n^2^),在進行大量數據處理時會消耗大量資源。並且該方法沒法處理字符和數組,以下例:面試

var arr = [1,23,4,5,6,7,'1',22,3,1,2];
distinct(arr);                  //返回[23, 4, 5, 6, 7, "1", 22, 3, 1, 2]

因此咱們能夠開始考慮一些別的方法優化數組去重:chrome

sort重排數組去除重複元素索引法(!每個瀏覽器中的sort函數的排序方法並不同,因此實現結果可能會有差別,經測試在chrome下測試別的數組實現會出現問題)

這種方法就是先講原數組使用sort方法將數組重排,以獲得將相同元素爲相鄰位的一個新數組。該方法以下:json

function distinct(arr){
    var self = arr;
        list = self.concat().sort();
        
    list.sort(function(a, b){
        if(a === b){
            var ind = self.indexOf(a);
            self.splice(ind, 1);
        }
    });
    return self;
}
var arra = [1,2,3,3,1,1,1,'1'];
var arr = distinct(arra);                //返回的數組爲[2,3,1,'1']

一樣的,在使用這種方法的重排的時候,仍然會有必定的資源消耗,在sort()函數中回調函數是使用的冒泡排序,而冒泡排序的效率並不高。可是使用這種方法的效率仍然比上一種方法的效率高,由於在此例中只出現了一次循環遍歷。

優勢:程序簡潔,效率較高。
缺點:1.仍然沒法解決數字1和字符'1'的去除。2.依賴indexOf方法,咱們知道在IE6~8中並未支持indexOf()方法。
因此咱們還要作一些兼容性的處理。以下:

var indexOf = [].indexOf ?
    function indexOf(arr, item){
        return arr.indexOf(item);
    }:
    function indexOf(arr, item){
        for(var i = 0; i < arr.length; i++){
            if(arr[i] === item){
                retrun i;            
            }
        }
        return -1;
    }
    
function distinct(arr){
    var self = arr;
        list = self.concat().sort();
        
    list.sort(function(a, b){
        if(a === b){
            var ind = self.indexOf(arr, a);
            self.splice(ind, 1);
        }
    });
    return self;
}

將數組元素值存爲對象的屬性

function distinct(arr) {
    var ret = [],
        json = {},
        length = arr.length;
        
    for(var i = 0; i < length; i++){
        var val = arr[i];
        if(!json[val]){
            json[val] = 1;
            ret.push(val);
        }
    }
    return ret;
}

var arra = [1,2,3,5,7,1,2,'1'];

以上方法更加的簡潔,並且也能在原來的基礎上區分字符‘1’和數字1的區別。
在此例中思路以下:
1.循環遍歷每個元素
2.檢測在json對象中是否含遍歷到的元素的值

a: 若是是則跳過
b: 若是否存入json對象中該屬性名的值設爲1

3.將存入對象了元素的值推入到新數組中,返回新數組。

總結,其實數組去重無非就是判斷一個元素在數組中是否有重複的值。優化也是一直改變斷定元素是否重複的一些技巧,如例1中是遍歷數組,例2是重排數組得到索引,例3則別出心裁將元素的值做爲對象的屬性。

參考自:
從 JavaScript 數組去重談性能優化
也談javascript數組去重
js數組去重

謝謝@飛的更高 指出的問題

同步於我的博客:http://penouc.com

相關文章
相關標籤/搜索