国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript 中對(duì)大量數(shù)據(jù)的多重過(guò)濾

leoperfect / 1854人閱讀

摘要:如果要這樣做,就需要將選擇的過(guò)濾條件先記錄下來(lái)。現(xiàn)在再用最后取得的依次來(lái)過(guò)濾原數(shù)據(jù),就能得到正確的結(jié)果。不過(guò)這樣我覺(jué)得效率不太好,尤其是對(duì)大量數(shù)據(jù)的時(shí)候。

所有代碼使用 ES2015 語(yǔ)法,需要 ES5 語(yǔ)法的可以用 Babel - Try it out 或者 TypeScript Playground 翻譯。

問(wèn)題提出

今天有朋友問(wèn)我一個(gè)問(wèn)題,前端通過(guò) Ajax 從后端取得了大量的數(shù)據(jù),需要根據(jù)一些條件過(guò)濾,過(guò)濾的方法是這樣的:

class Filter {
    filterA(s) {
        let data = this.filterData || this.data;
        this.filterData = data.filter(m => m.a === s);
    }
    
    filterB(s) {
        let data = this.filterData || this.data;
        this.filterData = data.filter(m => m.b === s);
    }
}

現(xiàn)在迷糊了,覺(jué)得這樣處理數(shù)據(jù)不對(duì),但是又不知道該怎么處理。

發(fā)現(xiàn)問(wèn)題

問(wèn)題就在過(guò)濾上,這樣固然可以實(shí)現(xiàn)多重過(guò)濾(先調(diào)用 filterA() 再調(diào)用 filterB() 就可以實(shí)現(xiàn)),但是這個(gè)過(guò)濾是不可逆的。假如過(guò)濾過(guò)程是這樣:

f.filterA("a1");
f.filterB("b1");
f.filterA("a2");

本來(lái)是希望按 "a1""b1" 過(guò)濾了數(shù)據(jù)之后,再修改第一個(gè)條件為 "a2",但結(jié)果卻成了空集。

解決問(wèn)題

發(fā)現(xiàn)了問(wèn)題,就針對(duì)性的解決。這個(gè)問(wèn)題既然是因?yàn)檫^(guò)濾過(guò)程不可逆造成的,那每次都直接從 this.data 開(kāi)始過(guò)濾,而不是從 this.filterData 開(kāi)始過(guò)濾,就能解決問(wèn)題。如果要這樣做,就需要將選擇的過(guò)濾條件先記錄下來(lái)。

記錄過(guò)濾條件

用一個(gè)列表記錄過(guò)濾條件當(dāng)然是可行的,但是注意對(duì)同一個(gè)條件的兩次過(guò)濾是互斥的,只能保留最后一個(gè),所以應(yīng)該用 HashMap 更為合適。

class Filter {
    constructor() {
        this.filters = {};
    }

    set(key, filter) {
        this.filters[key] = filter;
    }

    getFilters() {
        return Object.keys(this.filters).map(key => this.filters[key]);
    }
}

這種情況下,像上面的過(guò)程表示為

f.set("A", m => m.a === "a1");
f.set("B", m => m.b === "b1");
f.set("A", m => m.a === "a1");

let filters = f.getFilters();  // length === 2;

上面第 3 句設(shè)置的 filter 覆蓋了第 1 句設(shè)置的那個(gè)?,F(xiàn)在再用最后取得的 filters 依次來(lái)過(guò)濾原數(shù)據(jù) this.data,就能得到正確的結(jié)果。

有人會(huì)覺(jué)得 getFilters() 返回的列表不是按 set 的順序的——的確,這是 HashMap 的特點(diǎn),無(wú)序。不過(guò)對(duì)于簡(jiǎn)單條件的判斷,不管誰(shuí)先誰(shuí)后,結(jié)果是一樣的。但是對(duì)于一些復(fù)合條件判斷,就可能會(huì)有影響。

確實(shí)需要的話(huà),可以通過(guò) array 代替 map 來(lái)解決一下順序的問(wèn)題,但這樣查找效率會(huì)降低(線(xiàn)性查找)。如果還想解決查找效率的問(wèn)題,可以用 array + map 來(lái)處理。這里就不多說(shuō)了。

過(guò)濾

實(shí)際上在使用的時(shí)候,每次都 getFilter() 再用一個(gè)循環(huán)來(lái)處理確實(shí)比較慢。既然 data 都封裝成 Filter 中,可以考慮直接給一個(gè) filter() 方法來(lái)作為過(guò)濾接口。

class Filter {
    filter() {
        let data = this.data;
        for (let f of this.getFilters()) {
            data = data.filter(f);
        }
        return data;
    }
}

不過(guò)這樣我覺(jué)得效率不太好,尤其是對(duì)大量數(shù)據(jù)的時(shí)候。不妨利用一下 lodash 的延遲處理過(guò)程。

利用 lodash 的延遲處理
filter() {
    let chain = _(this.data);
    for (let f of this.getFilters()) {
        chain = chain.filter(f);
    }
    return chain.value();
}

lodash 在數(shù)據(jù)大于 200 的時(shí)候會(huì)啟用延遲處理過(guò)程,也就是說(shuō),它會(huì)處理成一個(gè)循環(huán)中依次調(diào)用每一個(gè) filter,而不是對(duì)每一個(gè) filter 進(jìn)行一次循環(huán)。

延遲處理和非延遲處理通過(guò)下圖可以看出來(lái)區(qū)別。非延遲處理總共會(huì)進(jìn)行 n(這里 n = 3) 次大循環(huán),產(chǎn)生 n - 1 個(gè)中間結(jié)果。而延遲處理只會(huì)進(jìn)行一次大循環(huán),沒(méi)有中間結(jié)果產(chǎn)生。

不過(guò)說(shuō)實(shí)在的,我不太喜歡為了一點(diǎn)小事多加載一個(gè)庫(kù),所以干脆自己做個(gè)簡(jiǎn)單的實(shí)現(xiàn)

自己實(shí)現(xiàn)延遲處理
filter() {
    const filters = this.getFilters();
    return data.filter(m => {
        for (let f of filters) {
            // 如果某個(gè) filter 已經(jīng)把它過(guò)濾掉了,也不用再用后面的 filter 來(lái)判斷了
            if (!f(m)) {
                return false;
            }
        }
        return true;
    });
}

里面的 for 循環(huán)還可以用 Array.prototype.every 來(lái)簡(jiǎn)化:

filter() {
    const filters = this.getFilters();
    return data.filter(m => {
        return filters.every(f => f(m));
    });
}

數(shù)據(jù)過(guò)濾其實(shí)并不是多復(fù)雜的事情,只要把思路理清楚,搞明白什么數(shù)據(jù)是需要保留的,什么數(shù)據(jù)是臨時(shí)(中間過(guò)程)的,什么數(shù)據(jù)是最終結(jié)果……利用 Array.prototype 中的相關(guān)方法,或者諸如 lodash 之類(lèi)的工具,很容易就處理出來(lái)了。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80752.html

相關(guān)文章

  • HTTP識(shí)別,認(rèn)證與安全——《HTTP權(quán)威指南》系列

    摘要:首發(fā)地址識(shí)別認(rèn)證與安全第三部分的章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。安全使用基本認(rèn)證的唯一方式就是將其與配合使用。加密之前的原始報(bào)文通常被稱(chēng)為明文或。 WilsonLius blog 首發(fā)地址 識(shí)別,認(rèn)證與安全 第三部分的4章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。 客戶(hù)端識(shí)別與cookie機(jī)制 第十一章 H...

    asce1885 評(píng)論0 收藏0
  • HTTP識(shí)別,認(rèn)證與安全——《HTTP權(quán)威指南》系列

    摘要:首發(fā)地址識(shí)別認(rèn)證與安全第三部分的章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。安全使用基本認(rèn)證的唯一方式就是將其與配合使用。加密之前的原始報(bào)文通常被稱(chēng)為明文或。 WilsonLius blog 首發(fā)地址 識(shí)別,認(rèn)證與安全 第三部分的4章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。 客戶(hù)端識(shí)別與cookie機(jī)制 第十一章 H...

    Jason_Geng 評(píng)論0 收藏0
  • HTTP識(shí)別,認(rèn)證與安全——《HTTP權(quán)威指南》系列

    摘要:首發(fā)地址識(shí)別認(rèn)證與安全第三部分的章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。安全使用基本認(rèn)證的唯一方式就是將其與配合使用。加密之前的原始報(bào)文通常被稱(chēng)為明文或。 WilsonLius blog 首發(fā)地址 識(shí)別,認(rèn)證與安全 第三部分的4章提供了一系列的技術(shù)和機(jī)器,可用來(lái)跟蹤身份,進(jìn)行安全性檢測(cè),控制對(duì)內(nèi)容的訪(fǎng)問(wèn)。 客戶(hù)端識(shí)別與cookie機(jī)制 第十一章 H...

    call_me_R 評(píng)論0 收藏0
  • 用戶(hù)只有一部手機(jī),怎么保護(hù)私鑰—— mixin如何實(shí)現(xiàn)資產(chǎn)安全

    摘要:比特幣白皮書(shū)都發(fā)布了年,這一種資產(chǎn)保護(hù)模式一直延續(xù)到現(xiàn)在。如果考慮到一個(gè)人除了比特幣以外如果還擁有其他數(shù)字資產(chǎn),一個(gè)資產(chǎn)一個(gè)私鑰,那么私鑰的管理難度就更大了。以用戶(hù)在網(wǎng)絡(luò)存儲(chǔ)比特幣為例。用戶(hù)存入的比特幣只有經(jīng)過(guò)節(jié)點(diǎn)批準(zhǔn)才能提走。 **Mixin開(kāi)發(fā)者大賽正在進(jìn)行中,javascript, python, ruby, go程序員都可以來(lái)贏(yíng)30萬(wàn)大獎(jiǎng)。 大賽地址活動(dòng)地址 mixin.one...

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

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

0條評(píng)論

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