2012-12-27 6 views
5

Angenommen, ich habe ein Array. Ich möchte alle Elemente innerhalb des Arrays entfernen, die einen bestimmten Wert haben. Weiß jemand, wie man das macht? Der Wert, den ich entfernen möchte, kann mehr als einmal vorkommen und das Array wird nicht unbedingt sortiert. Ich würde es vorziehen, das Array an Ort und Stelle zu filtern, anstatt ein neues Array zu erstellen. Wenn Sie beispielsweise den Wert 2 aus dem Array [1, 2, 3, 2, 4] entfernen, sollte das Ergebnis [1, 3, 4] ausgegeben werden.Entfernen aller Vorkommen eines gegebenen Wertes von einem Array in D

Das ist das Beste, was ich tun konnte:

T[] without(T)(T[] stuff, T thingToExclude) { 
    auto length = stuff.length; 
    T[] result; 
    foreach (thing; stuff) { 
     if (thing != thingToExclude) { 
      result ~= thing; 
     } 
    } 
    return result; 
} 

stuff = stuff.without(thingToExclude); 
writeln(stuff); 

Dies scheint unnötig komplex und ineffizient. Gibt es einen einfacheren Weg? Ich schaute auf das Modul std.algorithm in der Standardbibliothek, in der Hoffnung, etwas hilfreiches zu finden, aber alles, was so aussah, als würde es tun, was ich wollte, war problematisch. Hier sind einige Beispiele für Dinge, die ich versuchte, die nicht funktioniert hat:

import std.stdio, std.algorithm, std.conv; 

auto stuff = [1, 2, 3, 2, 4]; 
auto thingToExclude = 2; 

/* Works fine with a hard-coded constant but compiler throws an error when 
    given a value unknowable by the compiler: 
    variable thingToExclude cannot be read at compile time */ 
stuff = filter!("a != " ~ to!string(thingToExclude))(stuff); 
writeln(stuff); 

/* Works fine if I pass the result directly to writeln but compiler throws 
    an error if I try assigning it to a variable such as stuff: 
    cannot implicitly convert expression (filter(stuff)) of type FilterResult!(__lambda2,int[]) to int[] */ 
stuff = filter!((a) { return a != thingToExclude; })(stuff); 
writeln(stuff); 

/* Mysterious error from compiler: 
    template to(A...) if (!isRawStaticArray!(A)) cannot be sliced with [] */ 
stuff = to!int[](filter!((a) { return a != thingToExclude; })(stuff)); 
writeln(stuff); 

So wie kann ich alle Vorkommen eines Wertes aus einem Array entfernen, ohne die Indizes zu wissen, wo sie erscheinen?

+1

Das Problem mit Ihrem letzten Versuch ist Operator Vorrang: 'zu! Int []' Instanziierung der 'to (T)' Vorlage und dann Anwendung von '[]', d.h. der Slice-Operator. Wenn Sie die Klammern als Teil des Zieltyps haben wollen, brauchen Sie parens: 'to! (Int []) (...)'. Es wird immer noch nicht funktionieren, aber es ist semantisch korrekt. – scry

Antwort

9

std.algorithm.filter ist ziemlich nah an dem, was Sie wollen: Ihr zweiter Versuch ist gut.

Sie möchten es entweder einer neuen Variablen zuweisen oder die array() - Funktion verwenden.

auto stuffWithoutThing = filter!((a) { return a != thingToExclude; })(stuff); 
// use stuffWithoutThing 

oder

stuff = array(filter!((a) { return a != thingToExclude; })(stuff)); 

Der erste schafft nicht ein neues Array. Es liefert nur Iteration über die Sache mit dem gegebenen Ding herausgefiltert.

Die zweite wird Speicher für ein neues Array reservieren, um den Inhalt zu halten. Sie müssen das Modul std.array importieren, damit es funktioniert.

+0

Ich habe ein paar kleine Korrekturen vorgenommen, und jetzt beschreibt Ihr Post genau das, was ich versucht habe. Vielen Dank. –

3

wenn Sie die Werte entfernen möchten, können Sie

auto stuffWithoutThing = remove!((a) { return a == thingToExclude; })(stuff); 

diese zuteilen wird kein neues Array, aber die Arbeit an Ort und Stelle verwenden entfernen, beachten Sie, dass die stuff Bereich wandelbar sein muss

+1

Sie sagen "dies wird kein neues Array zuweisen, sondern an Ort und Stelle arbeiten". Was meinst du damit? Werden Änderungen am 'stuff' Array vorgenommen? Wenn ja, was ist der Sinn der Zuordnung zu 'stuffWithoutThing'? –

+0

ja es wird Änderungen an Sachen, der Punkt der Zuweisung ist, so dass Sie wissen, die neue Länge der Stuff-Array –

+1

Warum muss ich zuweisen, nur um die Länge zu wissen? Warum kann ich nicht einfach die Länge von "Zeug" überprüfen? –

5

Funktion nachschlagen Entfernen Sie in http://dlang.org/phobos/std_algorithm.html. Es gibt zwei Strategien - stabil und instabil, je nachdem, ob die verbleibenden Elemente ihre relativen Positionen beibehalten sollen. Beide Strategien funktionieren an Ort und Stelle und haben O (n) -Komplexität. Die instabile Version schreibt weniger.

Verwandte Themen