URL: https://www.overclockers.at/coding-stuff/js-unique-werte-aus-array-columns_224660/page_1 - zur Vollversion wechseln!
Hallo.
Ich hab hier ein Problem mit der Performance der JS-Engine von Internet Explorer 7.
Ich habe ein Array mit ca. 300 - 350 verschiedenen Einträgen. In manchen Columns liegen Strings, die mit IDs gefüllt sind und sich mit den Einträgen in anderen überschneiden :
Eintrag 1: "101;102;103;104;"
Eintrag 2: "101;103;106;" etc.
Nun möchte ich aus allen Einträgen im Array, nachdem eine Filterung passiert ist, alle übergebliebenen IDs einmalig in einem Array abgespeichert haben. Mittels diesen werden dann Filterkategorien ein- oder ausgeblendet. Für DOM-Manipulation kommt jQuery 1.6 zum Einsatz.
Hab mir hier kurz etwas gebastelt, bin mir aber ziemlich sicher, dass diese Lösung in Hinsicht auf Performance noch einiges zu wünschen übrig lässt:
Code: JSvar _uniques = documentFinder.datTable.fnGetFilteredData(); var lists = $('#tableHead .itunes .list-holder ul'); var ct = 1; var uCol = []; while(ct <= 4){ var uniqueCol = ""; var li= ct-1; var x=0; for(x; x <_uniques.length; x=x+1){ if(ct===1){ uniqueCol += (_uniques[x][ct])+";"; }else{ uniqueCol += (_uniques[x][ct]); } } uCol[li] = uniqueCol.split(";"); uCol[li] = uCol[li].unique(); uCol[li].pop(); var itemCt = 0; lists.eq(li).find('li').each(function(){ var reqtitle = ""; if(itemCt != 0){ if(ct===1){ reqtitle = $(this).find("a").text(); }else{ reqtitle = $(this).attr("itemid"); } var hide = true; if($.inArray(reqtitle, uCol[li]) >= 0){ hide = false; } if (!hide) { $(this).show(); } else { $(this).hide(); } } itemCt++; }); ct++; } Array.prototype.unique = function () { var o = {}, i, l = this.length, r = []; for (i = 0; i < l; i += 1) o[this[i]] = this[i]; for (i in o) r.push(o[i]); return r; };
Deine Lösung lässt vor allem Dokumentation zu wünschen übrig.
Würd mal sagen dass du bessere Performance haben wirst wenn du mit dem Object aus "Array.prototype.unique" weiter arbeitest statt mit einem Array. Wegen
"32: [...] $.inArray(...)"
Object-Properties sind in ner HashMap gespeichert, dadurch haben die konstante Laufzeit beim Zugriff, inArray sucht dir im Schnitt jedes mal das halbe Array durch, egal wie gut die Suche is.
Dein zweites Problem dürfte (je nach Dokumentgröße) die Zeile sein:
22: lists.eq(li).find('li').each(...)
da weiss ich aber im Moment keine Lösung
Wenn Du eh jQuery verwendest, hast Du schon mit der jQuery Funktion getestet? http://api.jquery.com/jQuery.unique/
"Note that this only works on arrays of DOM elements"Zitat von DirtyHarryWenn Du eh jQuery verwendest, hast Du schon mit der jQuery Funktion getestet? http://api.jquery.com/jQuery.unique/
so, sorry, hatte wahnsinnig viele andere Dinge um die Ohren die letzten Tage, danke schon mal für die Antworten.
Habe die ganze Funktion noch mal umgekrempelt, weil ich pro Kategorie-Liste einmal über das ganze Daten-Array iteriert habe.
Sorry für die miese Kommentierung des ganzen, habe versucht die wichtigsten Schritte nun ein bisschen zu erklären.
Code: JSfiltering: function (c, sStr) { var searchString = ""; //Filter DataTable //First col -> plain string if(c === 1){ documentFinder.datTable.fnFilter(sStr, 1, true, true, true); //Additional cols -> regex }else{ searchString = documentFinder.selectedCols[0]+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]; documentFinder.datTable.fnFilter(searchString, 5, true, true, true); } //Get filtered data-Array var _uniques = documentFinder.datTable.fnGetFilteredData(); //Get DOM-Elements of sorting-lists var lists = $('#tableHead .itunes .list-holder ul'); //Declaration of data-arrays var sysFHT = []; var bwHT = []; var btHT = []; var anfHT = []; var cohHT = []; var uniqueCol = []; uniqueCol[0] = "";uniqueCol[1] = "";uniqueCol[2] = "";uniqueCol[3] = "";uniqueCol[4] = ""; //Add all data-strings together in specific uniqueCol-Array var x, max; for(x=0,max=_uniques.length; x < max; x+=1){ var y; for(y=1; y<6; y+=1){ if(y===1){ uniqueCol[y-1] += _uniques[x][y] + ";"; //Add ; to end of first-col data for splitting } else{ uniqueCol[y-1] += _uniques[x][y]; } } } //Create string that holds all unique coherency-strings for regex-search var ustr = uniqueCol[4].split(";"); cohHT = ustr.unique(); cohHT.pop(); var strstr = cohHT.join(""); //Iterate over all ul-sorting columns var z; for(z=0;z<4;z+=1){ var clmStr = uniqueCol[z].split(";"); var uCol = []; //adding column-specific data to uCol if(z===0){ sysFHT = clmStr.hash(); uCol = sysFHT; }else if(z===1){ bwHT = clmStr.hash(); uCol = bwHT; }else if(z===2){ btHT = clmStr.hash(); uCol = btHT; }else if(z===3){ anfHT = clmStr.hash(); uCol = anfHT; } if(z!==4){ var itemCt = 0; //Iterate over all li-elements lists.eq(z).find('li').each(function(){ var reqtitle = "", nsStr= ""; if(itemCt != 0){ //get filtering data if(z===0){ reqtitle = $(this).find("a").text(); //string for col 1 }else{ reqtitle = $(this).attr("itemid"); //given id for other columns //Build column-specific regex if(z===1){ nsStr = reqtitle+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]; }else if(z===2){ nsStr = documentFinder.selectedCols[0]+"_"+reqtitle+"_"+documentFinder.selectedCols[2]; }else if(z===3){ nsStr = documentFinder.selectedCols[0]+"_"+documentFinder.selectedCols[1]+"_"+reqtitle; } } //see if searchItem still exists in filtered data as plain string if((reqtitle in uCol) === false){ $(this).addClass("hidden"); }else{ //see if searchItem exists in any coherency in the product-list if(z!==0){ var found=false; if(strstr.search(nsStr) != -1){ found = true; } if(!found){ $(this).addClass("hidden"); }else{ $(this).removeClass("hidden"); } }else{ $(this).removeClass("hidden"); } } } itemCt++; }); } } }; //Returns Object : unique values as keys Array.prototype.hash = function () { var o = {}, i, l = this.length, r = []; for (i = 0; i < l; i += 1) o[this[i]] = null; return o; }; //Returns Array: unique data in value Array.prototype.unique = function () { var o = {}, i, l = this.length, r = []; for (i = 0; i < l; i += 1) o[this[i]] = null; for (i in o) r.push(i); return r; };
Bin grad nicht sicher ob ich was überseh, aber könnte man das nicht ausserhalb der .each(...) funktion auch machen?Code: JS//Build column-specific regex if(z===1){ nsStr = reqtitle+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]; }else if(z===2){ nsStr = documentFinder.selectedCols[0]+"_"+reqtitle+"_"+documentFinder.selectedCols[2]; }else if(z===3){ nsStr = documentFinder.selectedCols[0]+"_"+documentFinder.selectedCols[1]+"_"+reqtitle; }
Weisst was, poste mal Beispieldaten, und beschreibe nochmal was du erreichen willst anhand der Beispieldaten, ich glaub dass du zu kompliziert denkst
Der reqtitle ändert sich ja mit jedem einzelnen List-Element.
In diesem Code-Segment wird für jedes noch nicht gefilterte li-Element eine Regex-Suche zusammengestellt, die überprüft, ob dieses eine List-Element noch in irgendeiner vorhandenen Zusammenhängigkeit vorkommt.
Daten sehen folgendermaßen aus:
Code:["Testdata", "TestCategory", "100;101;102;103;", "1001;1002;1003;1004;1006;1007;", "10001;10002;10003;10004;10005;", "100_1001_10001;101_1001_10002;102_1001_10003;103_1001_10004;102_1002_10001;104_1003_10004;101_1003_10005;102_1001_10002;102_1004_10001;103_1003_10005;101_1005_10005;103_1005_10002;102_1006_10005;101_1007_10002;103_1007_10001;101_1008_10005;101_1009_10002;102_1010_10001;103_1009_10005;101_1007_10002;103_1009_10001;", "", ""]
Ich meinte DOM-Code 
Die Auswahllisten sind im Grunde nichts besonderes, so sehen sie aus nachdem sie von JavaScript befüllt worden sind
Code: HTML<div class="itunes"> <div class="list-holder"> <ul> <li itemid="1" class="active"><a href="#">Alle</a></li> <li itemid="2"><a href="#">Test 1</a></li> <li itemid="3"><a href="#">Test 2</a></li> <li itemid="4"><a href="#">Test 3</a></li> <li itemid="5"><a href="#">Test 4</a></li> <li itemid="6"><a href="#">Test 5</a></li> <div class="list-holder"> <ul> <li itemid="100" class="active"><a href="#">Alle</a></li> <li itemid="101"><a href="#">Test 1</a></li> <li itemid="102"><a href="#">Test 2</a></li> <li itemid="103"><a href="#">Test 3</a></li> <li itemid="104"><a href="#">Test 4</a></li> <li itemid="105"><a href="#">Test 5</a></li> </ul> </div> <div class="list-holder"> <ul> <li itemid="1000" class="active"><a href="#">Alle</a></li> <li itemid="1001"><a href="#">Test 1</a></li> <li itemid="1002"><a href="#">Test 2</a></li> <li itemid="1003"><a href="#">Test 3</a></li> <li itemid="1004"><a href="#">Test 4</a></li> <li itemid="1005"><a href="#">Test 5</a></li> </ul> </div> <div class="list-holder"> <ul> <li itemid="10000" class="active"><a href="#">Alle</a></li> <li itemid="10001"><a href="#">Test 1</a></li> <li itemid="10003"><a href="#">Test 2</a></li> <li itemid="10004"><a href="#">Test 3</a></li> <li itemid="10005"><a href="#">Test 4</a></li> <li itemid="10006"><a href="#">Test 5</a></li> </ul> </div> </div>
So, hab die Funktion jetzt nochmal umgekrempelt, um weniger Schleifendurchläufe und String-Operationen drin zu haben.
Funktioniert mit 300 Einträgen einigermaßen zufriedenstellend, 600 dauern dann schon etwas länger, ist aber noch im Bereich des ertragbaren (ich verlang ja von meiner 55 PS - Schüssel auch nicht, dass sie 250 fährt)
Code: JSfiltering: function (c, sStr) { var searchString = ""; //Filter DataTable //First col -> plain string if(c === 1){ documentFinder.datTable.fnFilter(sStr, 1, true, true, true); //Additional cols -> regex }else{ searchString = documentFinder.selectedCols[0]+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]+";"; documentFinder.datTable.fnFilter(searchString, 2, true, true, true); } //Get filtered data-Array var _uniques = documentFinder.datTable.fnGetFilteredData(); //Declaration of data-arrays var sysFHT = [], cohHT = [], uniqueCol = []; uniqueCol[0] = "";uniqueCol[1] = ""; //Add all data-strings together in specific uniqueCol-Array var x, max, y; for(x=0,max=_uniques.length; x < max; x+=1){ uniqueCol[0] += _uniques[x][1] + ";"; uniqueCol[1] += _uniques[x][2]; } //Create string that holds all unique coherency-strings for regex-search var ustr = uniqueCol[1].split(";"); cohHT = ustr.unique(); cohHT.pop(); var strstr = cohHT.join(";"); strstr += ";" //Iterate over all ul-sorting columns var z; for(z=0;z<4;z+=1){ //adding column-specific data to uCol if(z===0){ var clmStr = uniqueCol[0].split(";"); sysFHT = clmStr.hash(); } var itemCt = 0; //Iterate over all li-elements documentFinder.lists.eq(z).find('li').each(function(){ var reqtitle = "", nsStr= ""; if(itemCt !== 0){ //get filtering data if(z===0){ reqtitle = $(this).find("a").text(); //string for col 1 }else{ reqtitle = $(this).attr("itemid"); //given id for other columns //Build column-specific regex switch(z){ case 1: nsStr = reqtitle+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]+";"; break; case 2: nsStr = documentFinder.selectedCols[0]+"_"+reqtitle+"_"+documentFinder.selectedCols[2]+";"; break; case 3: nsStr = documentFinder.selectedCols[0]+"_"+documentFinder.selectedCols[1]+"_"+reqtitle+";"; break; } } if(z!==0){ var found=false; //see if searchItem exists in any coherency in the product-list if(strstr.search(nsStr) !== -1){ found = true; } if(!found){ $(this).addClass("hidden"); }else{ $(this).removeClass("hidden"); } }else{ //see if searchItem still exists in filtered data as plain string if((reqtitle in sysFHT) === false){ $(this).addClass("hidden"); }else{ $(this).removeClass("hidden"); } } } itemCt++; }); } $('#tableHead .itunes .list-holder').jScrollPane(); sysFHT = null; cohHT = null; uniqueCol = null; }
Warum?Code: JS(Zeile 31) var ustr = uniqueCol[1].split(";"); cohHT = ustr.unique(); cohHT.pop(); var strstr = cohHT.join(";"); strstr += ";" [...] (Zeile 69) if(strstr.search(nsStr) !== -1){ found = true; }
Geht das nicht auch so?Code: JS(Zeile 31) var ustr = uniqueCol[1].split(";"); var ustr_last = ustr.pop(); cohHT = ustr.hash(); cohHT[ustr_last] = null; var strstr = cohHT.join(";"); strstr += ";" [...] (Zeile 69) if(strstr[nsStr]){ found = true; }

Naja, das Problem ist, dass die Variable "nsStr" eine regex-Abfrage gespeichert hat, da wird mit Zugriff per Key etwas schwierig, weshalb ich auch die .search() - Methode verwende
was is hier regex?Code: PHPnsStr = reqtitle+"_"+documentFinder.selectedCols[1]+"_"+documentFinder.selectedCols[2]+";"
ist ne äußerst einfache. Teilweise stehen halt dann strings wie 101_...._.....; drin
overclockers.at v4.thecommunity
© all rights reserved by overclockers.at 2000-2026