Heim  >  Artikel  >  Web-Frontend  >  JS-Methode zur Mehrfachfilterung großer Datenmengen

JS-Methode zur Mehrfachfilterung großer Datenmengen

高洛峰
高洛峰Original
2016-12-07 16:08:291410Durchsuche

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


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;
 }
}

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.

JS-Methode zur Mehrfachfilterung großer Datenmengen

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;
 });
}

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.


Stellungnahme:
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