Heim >Web-Frontend >js-Tutorial >JS-Methode zur Mehrfachfilterung großer Datenmengen
Vorwort
Die Hauptanforderung besteht darin, dass das Front-End über Ajax eine große Datenmenge vom Back-End erhält, die gemäß einigen Bedingungen gefiltert werden muss. Die erste 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); } }
Jetzt bin ich 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.
Entdecken Sie das Problem
Das Problem liegt in der Filterung. Obwohl auf diese Weise eine Mehrfachfilterung erreicht werden kann (dies kann erreicht werden, indem zuerst filterA() und dann filterB() aufgerufen wird). , aber diese Filterung ist irreversibel.
Angenommen, der Filtervorgang sieht so aus:
f.filterA("a1"); f.filterB("b1"); f.filterA("a2");
Ursprünglich wollte ich die Daten nach „a1“ und „b1“ filtern. und ändern Sie dann die erste Bedingung in „a2“, aber das Ergebnis wird zu einer leeren 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 durchaus möglich, Filterbedingungen in einer Liste aufzuzeichnen. Beachten Sie jedoch, dass sich zwei Filter für dieselbe Bedingung gegenseitig ausschließen und nur der letzte dies kann beibehalten. Daher sollte es sinnvoller sein, HashMap zu verwenden.
class Filter { constructor() { this.filters = {}; } set(key, filter) { this.filters[key] = filter; } getFilters() { return Object.keys(this.filters).map(key => this.filters[key]); } }
In diesem Fall wird der obige Prozess 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;
Der im dritten Satz oben festgelegte Filter überschreibt den im ersten Satz festgelegten. 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 Array + Map verwenden. Hier gibt es nicht viel zu sagen. Filtern
class Filter { filter() { let data = this.data; for (let f of this.getFilters()) { data = data.filter(f); } return data; } }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. Verwendung der verzögerten Verarbeitung von lodash
filter() { let chain = _(this.data); for (let f of this.getFilters()) { chain = chain.filter(f); } return chain.value(); }lodash ermöglicht die verzögerte Verarbeitung, wenn die Daten größer als 200 sind, d. h Es wird so verarbeitet, dass jeder Filter nacheinander in einer Schleife aufgerufen wird, anstatt jeden Filter einmal zu durchlaufen. Der Unterschied zwischen verzögerter Verarbeitung und nicht verzögerter Verarbeitung ist in der Abbildung unten zu sehen. Die nicht verzögerte Verarbeitung führt insgesamt n (hier n = 3) große Schleifen durch und erzeugt n - 1 Zwischenergebnisse. Bei der verzögerten Verarbeitung wird nur eine große Schleife ausgeführt und es werden keine Zwischenergebnisse generiert. Aber um ehrlich zu sein, lade ich nicht gerne eine zusätzliche Bibliothek für triviale Dinge, also mache ich einfach selbst eine einfache ImplementierungVerzö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; }); }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)); }); }Datenfilterung ist eigentlich keine komplizierte Angelegenheit. Sie müssen lediglich Ihre Vorstellungen klären und herausfinden, welche Daten aufbewahrt werden müssen, welche Daten vorübergehend sind (Zwischenprozess) und welche Daten das Endergebnis sind ... Die zugehörigen Methoden in Array.prototype oder Tools wie lodash können problemlos verwendet werden.