Doubletten aus Array entfernen
Sebastian
- javascript
Hy,
Ich habe hier eine Funktion gebastelt, die aus einem Array Doubletten herausfiltern soll, die durch das mehrmalige Ausführen der Funktion test() an einem bestimmten Element entstehen.
/////////////////////////////////////
var elemente = new Array();
function test(element)
{
elemente.push(element.id);
elemente.sort();
for ( i = 0; i < elemente.length; i++)
{
while (elemente[i] == elemente[i-1])
elemente.splice(i,1);
}
}
/////////////////////////////////////
Ein solches Array würde ohne sort() z.B. so aussehen:
"Element1","Element1","Element2","Element1"
Nach sort() sähe das entsprechende Array dann so aus:
"Element1","Element1","Element1","Element2"
Mein Ansatz: in der for-Schleife wird jetzt jedes Element des Arrays mit dem vorangegangenen Element verglichen und geprüft, ob diese Elemente identisch sind. Ist dies der Fall, wird eines entfernt - und zwar solange, bis jedes Element nur noch einmal im Array vertreten ist.
Schön und gut ! Das funktioniert auch ! Aber mein Instinkt sagt mir, dass man das viel einfacher und eleganter lösen kann. Es sieht verdammt "gekrückt" aus, oder ? Wer kann mir eine "schönere" Lösung zeigen bzw. meiner Lösung seiner Segen geben ?
Kann man diese Aufgabe auch mit Regulären Ausdrücken erledigen ?
Mfg Sebastian
Moin!
Schön und gut ! Das funktioniert auch ! Aber mein Instinkt sagt mir, dass man das viel einfacher und eleganter lösen kann. Es sieht verdammt "gekrückt" aus, oder ? Wer kann mir eine "schönere" Lösung zeigen bzw. meiner Lösung seiner Segen geben ?
Du plenkst. Leerzeichen gehören hinter die Satzzeichen, nicht davor! Sieht eklig aus!
Ansonsten: Erstelle dir ein Objekt, das du als assoziatives Array benutzt. Die Strings deines Arrays werden zu den Schlüsselnamen des assoziativen Arrays. Du gehst jedes Element deines alten, unsortierten Arrays einmal durch, entnimmst den Elementnamen und nutzt diesen, um im assoziativen Array nachzusehen, ob ein Element dieses Namens schon existiert.
Alternativ addierst du einfach eine 1 zu diesem Element und hast hinterher die Anzahl der Elemente, die im alten Array waren.
Du kommst dann zurück zu einem bereinigten Array, indem du alle Elementnamen des assoziativen Arrays ausliest und wieder in ein normales Array packst. Sortieren wäre danach optional noch möglich.
Kann man diese Aufgabe auch mit Regulären Ausdrücken erledigen ?
Nein. Reguläre Ausdrücke arbeiten auf Stringbasis, du hast aber ein Array.
- Sven Rautenberg
Hallo,
Alles richtig, aber man könnte das noch weiter führen.
1. Warum überhaupt nachträglich Doppelte herausschneiden, warum keine eigene push-Funktion, die Doppelte erst gar nicht einträgt?
Array.prototype.add = function (element) {
if (!this.valuesObject) {
this.valuesObject = new Object();
}
if (typeof this.valuesObject[element] != "undefined") {
return false;
}
this.push(element);
this.valuesObject[element] = true;
return true;
};
var array = new Array();
array.add("a");
array.add("b");
array.add("c");
alert(array.join(", "));
array.add("a");
alert(array.join(", "));
Natürlich kann man dann die anderen Array-Methoden erst einmal nicht wie gewohnt verwenden, z.B. müsste man splice() mit einer Wrapper-Methode überschreiben, die dann zusätzlich delete this.valuesObject[element]; ausführt.
2. Wozu dient der Array konkret, welche Arraymethoden werdne verwendet? Reicht nicht ein Object aus, wenn man zum Prüfen der Doppelten sowieso ein Object mit exakt demselben Inhalt wie der Array speichern muss?
Mathias
- Warum überhaupt nachträglich Doppelte herausschneiden, warum keine eigene push-Funktion, die Doppelte erst gar nicht einträgt?
Ja, das ist die entscheidende Frage, die mich auch gequält halt.
Inzwischen habe ich auch folgende Lösung auf der Struppi-Seite gefunden.
////////////////////////////////////
Array.prototype.unique = function()
{
var o = {};
for(var i = 0 ; i < this.length; i++)
o[this[i]] = true;
var tmp = new Array();
for(var i in o) tmp[tmp.length] = i;
return tmp;
}
function test()
{
var T = new Array("Anton", "Bernd",
"Christian", "Daniel", "Erich", "Fritz", "Gabriel", "Fritz");
var neu = T.unique();
alert(neu);
}
////////////////////////////////////
Klappt - aber das Problem ist hier, dass ich hier nicht weiß, was da passiert. Das Skript müßte man mir wirklich Zeile_für_Zeile ins Doofen-Deutsch übersetzen - und wer von Euch hat da schon Lust drauf ... ;-)
Und einfach verwenden und nicht mehr drüber nachdenken - kann ich leider nicht ...
Mfg Sebastian
hi,
Klappt - aber das Problem ist hier, dass ich hier nicht weiß, was da passiert. Das Skript müßte man mir wirklich Zeile_für_Zeile ins Doofen-Deutsch übersetzen - und wer von Euch hat da schon Lust drauf ... ;-)
<translation from="javascript" to="doofen-deutsch">
Array.prototype.unique = function()
Dem Array-Objekt wird per prototype eine neue Methode hinzugefügt - diese besitzen danach _alle_ Array-Objekte, egal ob vorher schon oder danach erst erzeugt.
var o = {};
Die lokale Variable o wird als neues Object angelegt - ist das gleiche, wie var o = new Object();
for(var i = 0 ; i < this.length; i++)
o[this[i]] = true;
Hier passiert das "umdrehen", welches Sven schon erwähnte:
Für jedes Array-Element mit dem Wert "xyz" wird eine Object-Eigenschaft xyz hinzugefügt, und mit dem Wert true versehen.
Da Objekteigenschaften eindeutige Namen haben, würde das nächste Array-Element, dessen Wert auch "xyz" ist, hier keine weitere Objekt-Eigenschaft erzeugen, sondern die bereits vorhandene überschreiben - wiederum mit dem Wert true.
Wir haben also nach Ablauf dieser Schleife ein Objekt, welches für jeden _mindestens_ einmal im Array vorkommenden Wert eine gleichnamige Eigenschaft mit dem Wert true besitzt. Kam ein Wert im Array mehrmals vor, haben wir trotzdem nur _genau eine_ solche Eigenschaft - weil wegen Eindeutigkeit von Eigenschaftnamen und "Überschreibung".
Also haben wir jetzt schon dafür gesorgt, dass die mehrmals vorkommenden Werte nur noch einmal vorhanden sind - nur derzeit noch "auf der falschen Seite", denn wenn wir ein Objekt mal als assoziatives Array ansehen, haben wir jetzt unsere Werte als Schlüssel - also müssen wir jetzt noch aus Schlüsseln wieder Werte machen, und einen neuen fortlaufenden nummerischen Index erzeugen.
var tmp = new Array();
Jetzt wird ein neues Array angelegt,
for(var i in o) tmp[tmp.length] = i;
und für jede Eigenschaft des Objektes o, deren Eigenschaften-Namen die for-in-Schleife in i liefert, ein neues Array-Element angelegt.
(Neue Elemente ans Ende eines nummerischen Arrays anfügen kann man nicht nur über die push-Methode, sondern auch, in dem man dem nächstfolgenden Index einfach den entsprechenden Wert zuweist. Und da Javascript bei 0 an zu zählen fängt, liefert in einem nummerischen Array mit fortlaufenden Schlüsseln die length-Eigenschaft immer den nächsten "noch freien" Index.)
return tmp;
Und jetzt wird noch das so neu erzeugte Array als Rückgabewert der Methode unique() zurückgegeben.
</translation>
gruß,
wahsaga
<translation from="javascript" to="doofen-deutsch">
....
</translation>
Ich hätte es nicht besser gekonnt ;-)
Ob das jetzt der Beste und der schnellste Weg ist, weiß ich auch nicht. Aber er ist kurz und überschaubar und hat keine Nachteile.
Struppi.
Herzlichen Dank - ich habs verstanden !! :)