JavaScript-數組去重由慢到快由繁到簡

来源:http://www.cnblogs.com/pengfei25/archive/2016/08/25/5808504.html
-Advertisement-
Play Games

indexOf去重 Array.prototype.unique1 = function() { var arr = []; for (var i = 0; i < this.length; i++) { var item = this[i]; if (arr.indexOf(item) -1) { ...


indexOf去重

Array.prototype.unique1 = function() {

      var arr = [];

      for (var i = 0; i < this.length; i++) {

        var item = this[i];

        if (arr.indexOf(item) === -1) {

              arr.push(item);

        }

      }

      return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique1(); //[1, 2, 3, "4", 4, "34"]

不過,在 IE6-8 下,數組的 indexOf 方法還不存在(雖然這已經算有點古老的話題了O(∩_∩)O~),但是,程式員就要寫一個indexOf方法:

 

var indexOf = [].indexOf ? function(arr, item) {

      return arr.indexOf(item);

} :

function indexOf(arr, item) {

      for (var i = 0; i < arr.length; i++) {

        if (arr[i] === item) {

              return i;

        }

      }

      return -1;

}

 

Array.prototype.unique2 = function() {

      var arr = [];

      for (var i = 0; i < this.length; i++) {

        var item = this[i];

        if (arr.indexOf(item) === -1) {

              arr.push(item);

        }

      }

      return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique2(); //[1, 2, 3, "4", 4, "34"]

indexOf還可以以這樣的去重思路:

 

Array.prototype.unique3 = function(){

    var arr = [this[0]]; 

    for(var i = 1; i < this.length; i++) 

    {

        if (this.indexOf(this[i]) == i){

            arr.push(this[i]);

        } 

    }

    return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique3(); //[1, 2, 3, "4", 4, "34"]



hash去重

以上indexOf正確性沒問題,但性能上,兩重迴圈會降低性能。那我們就用hash。

 

Array.prototype.unique4 = function() {

      var arr = [];

      var hash = {};

      for (var i = 0; i < this.length; i++) {

        var item = this[i];

        var key = typeof(item) + item

        if (hash[key] !== 1) {

              arr.push(item);

              hash[key] = 1;

        }

      } 

      return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique4(); //[1, 2, 3, "4", 4, "34"]

核心是構建了一個 hash 對象來替代 indexOf。空間換時間。註意在 JavaScript 里,對象的鍵值只能是字元串(當然,ES6提供了Map數據結構。它類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字元串,各種類型的值(包括對象)都可以當作鍵。也就是說,Object結構提供了“字元串—值”的對應,Map結構提供了“值—值”的對應,是一種更完善的Hash結構現。),因此需要var key = typeof(item) + item 來區分數值 1 和字元串 '1' 等情況。

 

那如果你想要'4' 和 4 被認為是相同的話(其他方法同理)

 

Array.prototype.unique5 = function(){

    var arr=[];

    var hash={};

    for(var i=0,len=this.length;i<len;i++){

        if(!hash[this[i]]){ 

            arr.push(this[i]);

            hash[this[i]]=true;

        }

    }

    return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique5(); //[1, 2, 3, "4", "34"]



排序後去重

Array.prototype.unique6 = function(){

    this.sort();

    var arr = [this[0]];

    for(var i = 1; i < this.length; i++){

        if( this[i] !== arr[arr.length-1]){

            arr.push(this[i]);

        }

    }

    return arr;

}

[1,2,3,'4',3,4,3,1,'34',2].unique6(); //[1, 2, 3, "34", "4", 4]

先把數組排序,然後比較相鄰的兩個值,排序的時候用的JS原生的sort方法,所以非常快。而這個方法的缺陷只有一點,比較字元時按照字元編碼的順序進行排序。所以會看到10排在2前面這種情況。不過在去重中不影響。不過,解決sort的這個問題,是sort方法接受一個參數,這個參數是一個方法:

 

function compare(value1,value2) {

    if (value1 < value2) {

        return -1;

    } else if (value1 > value2) {

        return 1;

    } else {

        return 0;

    }

}

[1,2,5,2,10,3,20].sort(compare);  //[1, 2, 2, 3, 5, 10, 20]

 

Set去重

ES6提供了新的數據結構Set。它類似於數組,但是成員的值都是唯一的,沒有重覆的值。現在瀏覽器正在全面支持,服務端的node也已經支持。

 

Array.prototype.unique7 = function(){

    return Array.from(new Set(this));

}

[1,2,3,'4',3,4,3,1,'34',2].unique7(); //[1, 2, 3, "4", 4, "34"]

 

方法庫

推薦一個方法庫Underscore.js,在node或瀏覽器js中都很受歡迎。

 

const _ = require('underscore');

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

 

測試時間

以上方法均可以用一個簡單的方法去測試一下所耗費的時間,然後對各個方法做比較擇優:

 

console.time("test");

[1,2,3,'4',3,4,3,1,'34',2].unique7();

console.timeEnd("test");

==> VM314:3 test: 0.378ms

讓數據變得大一點,就隨機創建100萬個數:

 

var arr = [];

var num = 0;

for(var i = 0; i < 1000000; i++){

    num = Math.floor(Math.random()*100);

    arr.push(num);

}

console.time("test");

arr.unique7();

console.timeEnd("test");

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 靜態 1.普通成員 普通成員都是屬於對象的 用對象調用 2.靜態成員 靜態成員是屬於類的 用類名調用 stactic 靜態關鍵字 註:靜態方法裡面不能包含普通成員 普通方法裡面可以包含靜態成員 用處:1.為了簡便,連接資料庫的時候,造連接對象類,使用靜態屬性直接返回連接對象。 2.兩個類之間傳遞信息 ...
  • 一、封裝 目的:保護類,讓類更加安全。 做法:讓類裡面的成員變數變為私有(即訪問修飾符)的,做相應的方法或者屬性去間接的操作成員變數 ※訪問修飾符 private 私有的 只能在該類中訪問 protected 受保護的 只能在該類和它的子類中訪問 public 公有的 在任何地方都可以訪問 △封裝成 ...
  • 本文提供一個簡單的方法實現一個流程的進度條載入效果,以便在頁面中可以通過它來更好地反饋耗時任務的完成進度。要實現這個功能,首先要考慮怎樣實現一個靜態的進度條效果,類似下麵這樣的: 這個倒是比較簡單,兩個div即可,bootstrap官方就提供有多種主題的進度條組件。如果自己要用,參照下別人的代碼,寫... ...
  • http://images2015.cnblogs.com/blog/877509/201608/877509-20160826005432819-958173773.png ...
  • 觀察者模式 觀察者模式也叫“訂閱者/發佈者”模式,定義對象間的一種一對多的依賴關係,發佈者可以向所有訂閱者發佈消息。 觀察者模式被廣泛地應用於JavaScript客戶端編程中。所有的瀏覽器事件(mouseover,keypress等)都是使用觀察者模式的例子。 使用這個模式的最主要目的就是促進對象之 ...
  • 問題描述 最近在做移動項目時遇到一個頁面滾動穿透問題,具體場景是這樣的,在一個可滾動的列表頁中彈出一個蒙層,蒙層中的內容是可滾動的,底部的父頁面理論上是不可滾動的,但是當滑動蒙層內容時,底部父頁面會跟隨滾動,這就是頁面滾動穿透的問題。這個是比較常見的問題,基本都會遇到,Google一下出解決方案也是 ...
  • 1、安裝node-v6.3.0-x64,安裝成功後再點擊node-v6.3.0-x64卸載(點擊remove)。 2、安裝node-v4.4.7-x64。 3、打開cmd命令行,輸入node -v,查看下版本,如果有顯示版本,說明已經安裝成功。 4、輸入npm -v,查看下npm的版本,如果有顯示版 ...
  • 其實今天的分享很簡單,只要你簡單瞭解Jq拓展方法,只要你會遍歷元素,那就能自己封裝出來。在工作中正是因為有了一個個這樣的方法,大大提升了我們的工作效率,減小了失誤次數。但是我們往往又經常使用別人封裝好的方法,這就很不爽了。 希望熱愛技術的園友們今後都能做一個,自己封裝方法,給整個公司用的人。 再也不 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...