成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

跟underscore一起學(xué)數(shù)組去重

flybywind / 2569人閱讀

摘要:引子數(shù)組去重是一個(gè)老生常談的話題,在面試中也經(jīng)常會(huì)被問道。其中如果數(shù)組是排序的,去重運(yùn)算效率更高,因?yàn)榕判蚰軌驅(qū)⑾嗤臄?shù)排列在一起,方便前后比較。當(dāng)數(shù)組有序?qū)τ趯?duì)象的去重,我們知道為,所以使用比較對(duì)象在實(shí)際場(chǎng)景中沒有意義。

引子

數(shù)組去重是一個(gè)老生常談的話題,在面試中也經(jīng)常會(huì)被問道。對(duì)于去重,有兩種主流思想:

先排序,線性遍歷后去重,時(shí)間復(fù)雜度O(n*log2n);

使用哈希,空間換時(shí)間,時(shí)間復(fù)雜度O(n);

上一篇文章,我分析了underscore的函數(shù)是如何組織的,我們能夠依照這種方法書寫自己的函數(shù)庫,這篇文章,來看看關(guān)于函數(shù)去重underscore是如何做的?

Underscore的去重 功能介紹

underscore的去重是指數(shù)組(Arrays)中uniq函數(shù),其API如下:

uniq   _.uniq(array, [isSorted], [iteratee]) 別名: unique   
說明:返回 array去重后的副本, 使用 === 做相等測(cè)試. 如果您確定 array 已經(jīng)排序, 那么給 isSorted 參數(shù)傳遞 true值, 此函數(shù)將運(yùn)行的更快的算法. 如果要處理對(duì)象元素, 傳參 iterator 來獲取要對(duì)比的屬性.

上述API主要想說明幾點(diǎn):

返回?cái)?shù)組副本,不影響原數(shù)組

相等的標(biāo)準(zhǔn)是a===b,表明不僅要值相等,類型也需要相等

如果數(shù)組是排序的,去重運(yùn)算效率更高

uniq也可以比較對(duì)象,前提是需要指定比較的對(duì)象屬性

我們簡(jiǎn)單使用以下_.uniq(array, [isSorted], [iteratee]),如下:

  console.log(_.uniq([1,4,2,2,3,3]));
  console.log(_.uniq([1,2,2,2,3,3],true));
  console.log(_.uniq([{
            name:1,
            gender:"male"
        },{
            name:2,
            gender:"female"
        },{
            name:2,
            gender:"male"
        },{
            name:4,
            gender:"male"
    }],true,"gender"));

結(jié)果如下:

去重思想及實(shí)現(xiàn)

underscore去重的核心思想:

新建結(jié)果集數(shù)組res,遍歷待去重?cái)?shù)組,將每個(gè)遍歷值在res數(shù)組中遍歷檢查,將不存在當(dāng)前res中的遍歷值壓入res中,最后輸出res數(shù)組。
    function uniq(array){
        var res = [];
        array.forEach(function(element) {
            if(res.indexOf(element)<0){
                res.push(element);
            }
        }, this);
        return res;
    }
    console.log(uniq([1,4,2,2,3,3]));  //[1,4,2,3]

其中如果數(shù)組是排序的,去重運(yùn)算效率更高,因?yàn)榕判蚰軌驅(qū)⑾嗤臄?shù)排列在一起,方便前后比較。

    function uniq(array, isSorted) {
        var res = [];
        var seen = null;

        array.forEach(function (element,index) {
            if (isSorted) { 
                //當(dāng)數(shù)組有序
                if(!index || seen !== element) res.push(element);
                seen = element;
            } else {
                if (res.indexOf(element) < 0) {
                    res.push(element);
                }
            }
        }, this);
        return res;
    }
    console.log(uniq([1,2,"2",3,3,3,5],true)); //(5)?[1, 2, "2", 3, 5]

對(duì)于對(duì)象的去重,我們知道{}==={}為false,所以使用===比較對(duì)象在實(shí)際場(chǎng)景中沒有意義。
在這里我舉個(gè)實(shí)際場(chǎng)景的例子:

我要在小組中選擇一名男生(male)和一名女生(female),小組組員情況如下:
var array = [{
    name:"Tom",
    gender:"female"
},{
    name:"Lucy",
    gender:"female"
},{
    name:"Edward",
    gender:"male"
},{
    name:"Molly",
    gender:"female"
}] 

我們修改上面的uniq

    function uniq(array, isSorted, iteratee) {
        var res = [];
        var seen = [];
        array.forEach(function (element, index) {
            if (iteratee) {
                //判斷iteratee是否存在,存在的話,取出真正要比較的屬性
                var computed = element[iteratee];
                if (seen.indexOf(computed) < 0) {
                    seen.push(computed);
                    res.push(element);
                }
            } else if (isSorted) {
                //當(dāng)數(shù)組有序
                if (!index || seen !== element) res.push(element);
                seen = element;
            } else {
                if (res.indexOf(element) < 0) {
                    res.push(element);
                }
            }
        }, this);
        return res;
    }
    console.log(uniq([{
            name:"Tom",
            gender:"female"
        },{
            name:"Lucy",
            gender:"female"
        },{
            name:"Edward",
            gender:"male"
        },{
            name:"Molly",
            gender:"female"
        }],true,"gender")); 

結(jié)果如下:

underscore的uniq的實(shí)現(xiàn),基本上使用的上述思想。在附錄中我附上了源碼和一些注釋。

關(guān)于去重的思考

上述我分析了underscore的uniq函數(shù)實(shí)現(xiàn),在這之前我也看過諸如《JavaScript去重的N種方法》...之類的文章,underscore中的uniq函數(shù)實(shí)現(xiàn)方法并不是最優(yōu)解,至少從時(shí)間復(fù)雜度來講不是最優(yōu)。
那么為什么underscore不用Set對(duì)象來解決去重問題,使用indexof查找的時(shí)間復(fù)雜度是O(n),而hash查詢是O(1)
我個(gè)人認(rèn)為Set是ES6中引的對(duì)象,underscore是為了考慮兼容性問題
那為什么不用obj作為Set的替代方案呢?
這里我猜是underscore的設(shè)計(jì)者只想用自己內(nèi)部實(shí)現(xiàn)的_.indexOf函數(shù)。此處是我的猜測(cè),大家如果有想法,歡迎大家留言!
下面我附上ES6的實(shí)現(xiàn)(大家最熟悉的):

var a = [1,1,2,3,4,4];
var res = [...new Set(a)];

再附上obj的實(shí)現(xiàn):

    function uniq(array,iteratee){
        var res = [];
        var obj = {};
        array.forEach(function(element) {
            var computed = element;
            if(iteratee) computed = element[iteratee];
            if(!obj.hasOwnProperty(computed))
                obj[(typeof computed)+"_"+JSON.stringify(computed)] = element;
            }, this);
            for(var p in obj){
                res.push(obj[p]);
            }
            return res;
        }
    uniq([1,"1",2,3,4,4]);// (5)?[1, "1", 2, 3, 4]
附錄

underscore的uniq函數(shù)源碼及注釋:

    _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (array == null) return [];
    if (!_.isBoolean(isSorted)) {
      //如果沒有排序
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    /**
    ** 此處_.iteratee
    **  function (key){
    *      return function(obj){
    *        return obj[key];
    *      }
    **  }
    **  key就是這里的iteratee(對(duì)象的屬性),這里使用了閉包
    **/
    if (iteratee != null) iteratee = _.iteratee(iteratee, context); 
    var result = [];//返回去重后的數(shù)組(副本)
    var seen = [];
    for (var i = 0, length = array.length; i < length; i++) {
      var value = array[i];//當(dāng)前比較值
      if (isSorted) {
        //如果i=0時(shí),或者seen(上一個(gè)值)不等于當(dāng)前值,放入去重?cái)?shù)組中
        if (!i || seen !== value) result.push(value); 
        seen = value;//保存當(dāng)前值,用于下一次比較
      } else if (iteratee) {
        var computed = iteratee(value, i, array);
        if (_.indexOf(seen, computed) < 0) {
          seen.push(computed);
          result.push(value);
        }
      } else if (_.indexOf(result, value) < 0) {
        result.push(value);
      }
    }
    return result;
  };

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102527.html

相關(guān)文章

  • JavaScript專題系列20篇正式完結(jié)!

    摘要:寫在前面專題系列是我寫的第二個(gè)系列,第一個(gè)系列是深入系列。專題系列自月日發(fā)布第一篇文章,到月日發(fā)布最后一篇,感謝各位朋友的收藏點(diǎn)贊,鼓勵(lì)指正。 寫在前面 JavaScript 專題系列是我寫的第二個(gè)系列,第一個(gè)系列是 JavaScript 深入系列。 JavaScript 專題系列共計(jì) 20 篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖、節(jié)流、去重、類型判斷、拷貝、最值、扁平、柯里...

    sixleaves 評(píng)論0 收藏0
  • 也談面試必備問題之 JavaScript 數(shù)組去重

    摘要:而數(shù)組元素去重是基于運(yùn)算符的。而如果有迭代函數(shù),則計(jì)算傳入迭代函數(shù)后的值,對(duì)值去重,調(diào)用方法,而該方法的核心就是調(diào)用方法,和我們上面說的方法一異曲同工。 Why underscore (覺得這部分眼熟的可以直接跳到下一段了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類庫的源碼,就好像...

    Coly 評(píng)論0 收藏0
  • JavaScript專題系列文章

    摘要:專題系列共計(jì)篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實(shí)現(xiàn)模式需求我們需要寫一個(gè)函數(shù),輸入,返回。 JavaScript 專題之從零實(shí)現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實(shí)現(xiàn)一個(gè) jQuery 的 ext...

    Maxiye 評(píng)論0 收藏0
  • underscore一起學(xué)如何寫函數(shù)庫

    摘要:支持兩種不同風(fēng)格的函數(shù)調(diào)用在中我們可以使用以下兩種方式調(diào)用函數(shù)式的調(diào)用對(duì)象式調(diào)用在中,它們返回的結(jié)果都是相同的。 原文:https://zhehuaxuan.github.io/... 作者:zhehuaxuan 目的 Underscore 是一個(gè) JavaScript 工具庫,它提供了一整套函數(shù)式編程的實(shí)用功能,但是沒有擴(kuò)展任何 JavaScript 內(nèi)置對(duì)象。 本文主要梳理und...

    ephererid 評(píng)論0 收藏0
  • JavaScript 數(shù)組展開以及 underscore 重要的內(nèi)部方法 flatten 詳解

    摘要:今天要講的是數(shù)組展開以及和數(shù)組展開息息相關(guān)的一個(gè)重要的內(nèi)部方法。也是個(gè)布爾值,當(dāng)為并且也為時(shí),能過濾參數(shù)元素中的非數(shù)組元素。首先并不需要對(duì)數(shù)組深度展開,其次傳入的是數(shù)組,對(duì)于非數(shù)組元素可以直接忽略。 Why underscore (覺得這一段眼熟的童鞋可以直接跳到正文了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 201...

    binaryTree 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<