2012-12-27 21 views
5

Supponiamo di disporre di una matrice. Voglio rimuovere tutti gli elementi all'interno della matrice che hanno un determinato valore. Qualcuno sa come fare questo? Il valore che sto cercando di rimuovere può verificarsi più di una volta e l'array non è necessariamente ordinato. Preferirei filtrare l'array sul posto invece di creare un nuovo array. Ad esempio, la rimozione del valore 2 dall'array [1, 2, 3, 2, 4] dovrebbe produrre il risultato [1, 3, 4].Rimozione di tutte le occorrenze di un determinato valore da una matrice in D

Questa è la cosa migliore che potessi venire con:

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

Questo sembra inutilmente complessa e inefficiente. c'è un modo più facile? Ho guardato il modulo std.algorithm nella libreria standard sperando di trovare qualcosa di utile, ma tutto ciò che sembrava farebbe ciò che volevo era problematico. Ecco alcuni esempi di cose che ho provato che non ha funzionato:

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

Così, come posso rimuovere tutte le occorrenze di un valore da un array senza conoscere gli indici in cui appaiono?

+1

Il problema con il tuo ultimo tentativo è la precedenza degli operatori: 'to! Int []' sta creando un'istanza del modello 'to (T)' e quindi applica '[]', cioè l'operatore della sezione. Se vuoi le parentesi come parte del tipo di destinazione hai bisogno di parens: 'to! (Int []) (...)'. Ancora non funzionerà, ma è semanticamente corretto. – scry

risposta

9

std.algorithm.filter è abbastanza vicino a quello che vuoi: il tuo secondo tentativo è buono.

Sarà necessario assegnarlo a una nuova variabile o utilizzare la funzione array() su di esso.

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

o

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

La prima non crea un nuovo array. Fornisce semplicemente l'iterazione sulla cosa con la cosa determinata filtrata.

Il secondo allocherà memoria per un nuovo array per contenere il contenuto. È necessario importare il modulo std.array affinché funzioni.

+0

Ho apportato alcune correzioni minori e ora il tuo post descrive esattamente cosa stavo cercando di fare. Grazie. –

3

se si desidera rimuovere i valori è possibile utilizzare rimuovere

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

questo non assegnerà un nuovo array, ma il lavoro in luogo, si noti che la gamma stuff deve essere mutabile

+1

Si dice "questo non alloca un nuovo array ma funziona sul posto". Cosa intendi con questo? Questo cambierà l'array 'stuff'? Se è così, allora che senso ha assegnare a "stuffWithoutThing"? –

+0

sì, si modificheranno le cose, il punto di assegnazione è quindi si conosce la nuova lunghezza dell'array roba –

+1

Perché devo assegnare solo per sapere la lunghezza? Perché non riesco a controllare la lunghezza di "cose"? –

5

Look up funzione rimuovere in http://dlang.org/phobos/std_algorithm.html. Esistono due strategie: stabili e instabili a seconda che si desideri che gli elementi rimanenti mantengano le loro posizioni relative. Entrambe le strategie funzionano e hanno O (n) complessità. La versione instabile fa meno scritture.

Problemi correlati