js專題:數(shù)組去重

最原始的方法:雙層循環(huán)

var array = [1, 1, '1', '1'];

function unique(array) {
    // res用來存儲結(jié)果
    var res = [];
    for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++ ) {
            if (array[i] === res[j]) {
                break;
            }
        }
        // 如果array[i]是唯一的涯冠,那么執(zhí)行完循環(huán)磁滚,j等于resLen
        if (j === resLen) {
            res.push(array[i])
        }
    }
    return res;
}

console.log(unique(array)); // [1, "1"]

在這個方法中拣挪,我們使用循環(huán)嵌套擦酌,最外層循環(huán) array,里面循環(huán) res菠劝,如果
array[i] 的值跟 res[j] 的值相等赊舶,就跳出循環(huán),如果都不等于赶诊,說明元素是
唯一的笼平,這時候 j 的值就會等于 res 的長度,根據(jù)這個特點(diǎn)進(jìn)行判斷舔痪,將值添
加進(jìn) res寓调。看起來很簡單吧锄码,之所以要講一講這個方法夺英,是因?yàn)椤嫒菪院茫?/p>

indexOf

我們可以用 indexOf 簡化內(nèi)層的循環(huán):

var array = [1, 1, '1'];

function unique(array) {
    var res = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var current = array[i];
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res;
}
console.log(unique(array));

排序后去重

var array = [1, 1, '1'];

function unique(array) {
    var res = [];
    var sortedArray = array.concat().sort();
    var seen;
    for (var i = 0, len = sortedArray.length; i < len; i++) {
        // 如果是第一個元素或者相鄰的元素不相同
        if (!i || seen !== sortedArray[i]) {
            res.push(sortedArray[i])
        }
        seen = sortedArray[i];
    }
    return res;
}

console.log(unique(array));

如果我們對一個已經(jīng)排好序的數(shù)組去重,這種方法效率肯定高于使用 indexOf滋捶。

unique API

知道了這兩種方法后痛悯,我們可以去嘗試寫一個名為 unique 的工具函數(shù),我們根據(jù)一個參數(shù) isSorted 判斷傳入的數(shù)組是否是已排序的炬太,如果為 true,我們就判斷相鄰元素是否相同驯耻,如果為 false亲族,我們就使用 indexOf 進(jìn)行判斷

var array1 = [1, 2, '1', 2, 1];
var array2 = [1, 1, '1', 2, 2];

// 第一版
function unique(array, isSorted) {
    var res = [];
    var seen = [];

    for (var i = 0, len = array.length; i < len; i++) {
        var value = array[i];
        if (isSorted) {
            if (!i || seen !== value) {
                res.push(value)
            }
            seen = value;
        }
        else if (res.indexOf(value) === -1) {
            res.push(value);
        }        
    }
    return res;
}

console.log(unique(array1)); // [1, 2, "1"]
console.log(unique(array2, true)); // [1, "1", 2]

優(yōu)化

盡管 unqique 已經(jīng)可以試下去重功能,但是為了讓這個 API 更加強(qiáng)大可缚,
我們來考慮一個需求:
新需求:字母的大小寫視為一致霎迫,比如'a'和'A',保留一個就可以了帘靡!
雖然我們可以先處理數(shù)組中的所有數(shù)據(jù)知给,比如將所有的字母轉(zhuǎn)成小寫,然后再
傳入unique函數(shù),但是有沒有方法可以省掉處理數(shù)組的這一遍循環(huán)涩赢,直接就在
去重的循環(huán)中做呢戈次?讓我們?nèi)ネ瓿蛇@個需求:

var array3 = [1, 1, 'a', 'A', 2, 2];

// 第二版
// iteratee 英文釋義:迭代 重復(fù)
function unique(array, isSorted, iteratee) {
    var res = [];
    var seen = [];

    for (var i = 0, len = array.length; i < len; i++) {
        var value = array[i];
        var computed = iteratee ? iteratee(value, i, array) : value;
        if (isSorted) {
            if (!i || seen !== computed) {
                res.push(value)
            }
            seen = computed;
        }
        else if (iteratee) {
            if (seen.indexOf(computed) === -1) {
                seen.push(computed);
                res.push(value);
            }
        }
        else if (res.indexOf(value) === -1) {
            res.push(value);
        }        
    }
    return res;
}

console.log(unique(array3, false, function(item){
    return typeof item == 'string' ? item.toLowerCase() : item
})); // [1, "a", 2]

在這一版也是最后一版的實(shí)現(xiàn)中,函數(shù)傳遞三個參數(shù):
array:表示要去重的數(shù)組筒扒,必填
isSorted:表示函數(shù)傳入的數(shù)組是否已排過序怯邪,如果為 true,將會采用更快的
方法進(jìn)行去重
iteratee:傳入一個函數(shù)花墩,可以對每個元素進(jìn)行重新的計算悬秉,然后根據(jù)處理的結(jié)
果進(jìn)行去重
至此,我們已經(jīng)仿照著 underscore 的思路寫了一個 unique 函數(shù)冰蘑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末和泌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子祠肥,更是在濱河造成了極大的恐慌武氓,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搪柑,死亡現(xiàn)場離奇詭異聋丝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)工碾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門弱睦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渊额,你說我怎么就攤上這事况木。” “怎么了旬迹?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵火惊,是天一觀的道長。 經(jīng)常有香客問我奔垦,道長屹耐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任椿猎,我火速辦了婚禮惶岭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘犯眠。我一直安慰自己按灶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布筐咧。 她就那樣靜靜地躺著鸯旁,像睡著了一般噪矛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铺罢,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天艇挨,我揣著相機(jī)與錄音,去河邊找鬼畏铆。 笑死雷袋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辞居。 我是一名探鬼主播楷怒,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓦灶!你這毒婦竟也來了鸠删?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贼陶,失蹤者是張志新(化名)和其女友劉穎刃泡,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碉怔,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烘贴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了撮胧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桨踪。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖芹啥,靈堂內(nèi)的尸體忽然破棺而出锻离,到底是詐尸還是另有隱情,我是刑警寧澤墓怀,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布汽纠,位于F島的核電站,受9級特大地震影響傀履,放射性物質(zhì)發(fā)生泄漏虱朵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一钓账、第九天 我趴在偏房一處隱蔽的房頂上張望碴犬。 院中可真熱鬧,春花似錦官扣、人聲如沸翅敌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春卖陵,著一層夾襖步出監(jiān)牢的瞬間遭顶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工泪蔫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棒旗,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓撩荣,卻偏偏與公主長得像铣揉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子餐曹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容