Heim > Web-Frontend > js-Tutorial > Hauptteil

Mehrfachfilterung großer Datenmengen in JavaScript

高洛峰
Freigeben: 2016-11-08 09:58:03
Original
1203 Leute haben es durchsucht

Der gesamte Code verwendet die ES2015-Syntax. Wer die ES5-Syntax benötigt, kann zum Übersetzen Babel – Try it out oder TypeScript Playground verwenden.

Frage gestellt

Ein Freund hat mir heute eine Frage gestellt. Das Front-End erhält über Ajax eine große Datenmenge vom Back-End, die nach bestimmten Bedingungen gefiltert werden muss . Die Filtermethode ist wie folgt:

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); 
    } 
}
Nach dem Login kopieren

Ich bin jetzt verwirrt und habe das Gefühl, dass es falsch ist, die Daten auf diese Weise zu verarbeiten, aber ich weiß nicht, wie ich sie verarbeiten soll.

Das Problem wurde gefunden

Das Problem liegt in der Filterung. Obwohl es möglich ist, eine Mehrfachfilterung zu erreichen (indem zuerst filterA() und dann filterB() aufgerufen werden), ist diese Filterung irreversibel. Angenommen, der Filtervorgang sieht folgendermaßen aus:

f.filterA("a1"); 
f.filterB("b1"); 
f.filterA("a2");
Nach dem Login kopieren

Ursprünglich wollte ich die Daten nach „a1“ und „b1“ filtern und dann die erste Bedingung in „a2“ ändern, aber das Ergebnis war so sei eine leere Menge.

Lösen Sie das Problem

Wenn Sie ein Problem finden, lösen Sie es entsprechend. Da dieses Problem durch den irreversiblen Filterprozess verursacht wird, kann das Problem gelöst werden, indem die Filterung jedes Mal direkt von this.data aus gestartet wird, anstatt von this.filterData aus. Wenn Sie dies tun möchten, müssen Sie zunächst die ausgewählten Filterbedingungen erfassen.

Filterbedingungen aufzeichnen

Es ist sicherlich möglich, Filterbedingungen in einer Liste aufzuzeichnen. Beachten Sie jedoch, dass sich zwei Filter für dieselbe Bedingung gegenseitig ausschließen und daher nur der letzte beibehalten werden kann Sie sollten HashMap verwenden, das besser geeignet ist.

class Filter { 
    constructor() { 
        this.filters = {}; 
    } 
 
    set(key, filter) { 
        this.filters[key] = filter; 
    } 
 
    getFilters() { 
        return Object.keys(this.filters).map(key => this.filters[key]); 
    } 
}
Nach dem Login kopieren

In diesem Fall wird der obige Prozess ausgedrückt als

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;
Nach dem Login kopieren

Der im 3. Satz oben festgelegte Filter deckt den im 1. Satz festgelegten Filter ab. Verwenden Sie nun die zuletzt erhaltenen Filter, um die Originaldaten this.data der Reihe nach zu filtern, und Sie erhalten das richtige Ergebnis.

Manche Leute denken vielleicht, dass die von getFilters() zurückgegebene Liste nicht in der Reihenfolge der Menge ist – tatsächlich ist dies das Merkmal von HashMap, das ungeordnet ist. Bei der Beurteilung einfacher Bedingungen ist das Ergebnis jedoch dasselbe, egal wer zuerst kommt. Bei manchen zusammengesetzten Zustandsbeurteilungen kann es jedoch Auswirkungen haben.

Bei Bedarf können Sie Array anstelle von Map verwenden, um das Reihenfolgeproblem zu lösen. Dies verringert jedoch die Sucheffizienz (lineare Suche). Wenn Sie das Problem der Sucheffizienz dennoch lösen möchten, können Sie es mithilfe einer Array-Karte lösen. Hier gibt es nicht viel zu sagen.

Filtern

Tatsächlich ist es bei der Verwendung sehr langsam, getFilter() zu verwenden und es dann jedes Mal mit einer Schleife zu verarbeiten. Da Daten in Filter gekapselt sind, können Sie erwägen, direkt eine filter()-Methode anzugeben, um die Filterschnittstelle bereitzustellen.

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

Ich denke jedoch, dass dies nicht sehr effizient ist, insbesondere wenn es um große Datenmengen geht. Sie können auch die verzögerte Verarbeitung von lodash nutzen.

Verzögerte Verarbeitung von lodash verwenden

filter() { 
    let chain = _(this.data); 
    for (let f of this.getFilters()) { 
        chain = chain.filter(f); 
    } 
    return chain.value(); 
}
Nach dem Login kopieren

lodash aktiviert die verzögerte Verarbeitung, wenn die Daten größer als 200 sind, das heißt, es verarbeitet sie in einer Schleife und ruft nacheinander jeden Filter auf . Anstatt jeden Filter zu durchlaufen.

Der Unterschied zwischen verzögerter Verarbeitung und nicht verzögerter Verarbeitung ist in der Abbildung unten zu sehen. Bei der unverzögerten Verarbeitung werden insgesamt n (hier n = 3) große Schleifen ausgeführt, was zu n - 1 Zwischenergebnissen führt. Bei der verzögerten Verarbeitung wird nur eine große Schleife ausgeführt und es werden keine Zwischenergebnisse generiert.

Mehrfachfilterung großer Datenmengen in JavaScript

Aber um ehrlich zu sein, lade ich nicht gerne eine zusätzliche Bibliothek für triviale Dinge, also mache ich einfach selbst eine einfache Implementierung

Verzögerungsverarbeitung implementieren Ich selbst

filter() { 
    const filters = this.getFilters(); 
    return data.filter(m => { 
        for (let f of filters) { 
            // 如果某个 filter 已经把它过滤掉了,也不用再用后面的 filter 来判断了 
            if (!f(m)) { 
                return false; 
            } 
        } 
        return true; 
    }); 
}
Nach dem Login kopieren

Die for-Schleife im Inneren kann auch mit Array.prototype.every vereinfacht werden:

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

Datenfilterung ist eigentlich keine komplizierte Angelegenheit, solange Sie die Ideen klären Sie können verstehen, welche Daten aufbewahrt werden müssen, welche Daten temporär sind (Zwischenprozess) und welche Daten das Endergebnis sind. Sie können problemlos mithilfe der entsprechenden Methoden in Array.prototype oder Tools wie lodash verarbeitet werden.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!