Angenommen, ein Array von n Objekten ist ein Array von Zeichenfolgen und hat die folgenden Werte:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Was muss ich tun, um alle Zeichenfolgen / Objekte zu löschen / zu entfernen, die "a" im Array entsprechen?
java
arrays
data-structures
data-manipulation
Ramayac
quelle
quelle
Antworten:
[Wenn Sie einen gebrauchsfertigen Code wünschen, scrollen Sie bitte zu "Edit3" (nach dem Schnitt). Der Rest ist für die Nachwelt da.]
Um Dustmans Idee zu konkretisieren :
List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array);
Bearbeiten: Ich verwende jetzt
Arrays.asList
anstelle vonCollections.singleton
: Singleton ist auf einen Eintrag beschränkt, während Sie mit diesemasList
Ansatz weitere Zeichenfolgen hinzufügen können, um sie später herauszufiltern :Arrays.asList("a", "b", "c")
.Edit2: Der obige Ansatz behält das gleiche Array bei (das Array hat also immer noch die gleiche Länge). Das Element nach dem letzten wird auf null gesetzt. Wenn Sie ein neues Array wünschen, dessen Größe genau den Anforderungen entspricht, verwenden Sie stattdessen Folgendes:
array = list.toArray(new String[0]);
Edit3: Wenn Sie diesen Code häufig in derselben Klasse verwenden, können Sie dies Ihrer Klasse hinzufügen:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Dann wird die Funktion:
List<String> list = new ArrayList<>(); Collections.addAll(list, array); list.removeAll(Arrays.asList("a")); array = list.toArray(EMPTY_STRING_ARRAY);
Dadurch wird Ihr Heap nicht mehr mit nutzlosen leeren String-Arrays übersät, die sonst bei
new
jedem Aufruf Ihrer Funktion bearbeitet würden .Der Vorschlag von Cynicalman (siehe Kommentare) hilft auch beim Müllhaufen, und der Fairness halber sollte ich ihn erwähnen:
array = list.toArray(new String[list.size()]);
Ich bevorzuge meinen Ansatz, weil es möglicherweise einfacher ist, die explizite Größe falsch zu bestimmen (z. B.
size()
die falsche Liste aufzurufen ).quelle
Eine Alternative in Java 8:
String[] filteredArray = Arrays.stream(array) .filter(e -> !e.equals(foo)).toArray(String[]::new);
quelle
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
wäre also ausreichend.Machen Sie
List
aus dem Array einArrays.asList()
und rufen Sieremove()
alle entsprechenden Elemente auf. Rufen Sie danntoArray()
die 'Liste' auf, um wieder in ein Array zurückzukehren.Nicht besonders performant, aber wenn Sie es richtig einkapseln, können Sie später immer etwas schneller machen.
quelle
Arrays.asList()
nicht unterstütztremove()
. Ist diese Antwort also völlig ungültig? Vielleicht wurden einige Kommentare entfernt, daher weiß ich nicht, ob dies besprochen wurde.Sie können immer tun:
int i, j; for (i = j = 0; j < foo.length; ++j) if (!"a".equals(foo[j])) foo[i++] = foo[j]; foo = Arrays.copyOf(foo, i);
quelle
Sie können eine externe Bibliothek verwenden:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Es ist im Projekt Apache Commons Lang http://commons.apache.org/lang/
quelle
ArrayUtils.removeElement(boolean[] array, boolean element)
ist auch sehr nützlich.Siehe Code unten
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings)); a.remove(i); strings = new String[a.size()]; a.toArray(strings);
quelle
Wenn Sie mehrere Elemente aus dem Array entfernen müssen, ohne es zu konvertieren
List
oder ein zusätzliches Array zu erstellen, können Sie dies in O (n) tun, unabhängig von der Anzahl der zu entfernenden Elemente.Hier
a
ist das anfängliche Array,int... r
sind verschiedene geordnete Indizes (Positionen) der zu entfernenden Elemente:public int removeItems(Object[] a, int... r) { int shift = 0; for (int i = 0; i < a.length; i++) { if (shift < r.length && i == r[shift]) // i-th item needs to be removed shift++; // increment `shift` else a[i - shift] = a[i]; // move i-th item `shift` positions left } for (int i = a.length - shift; i < a.length; i++) a[i] = null; // replace remaining items by nulls return a.length - shift; // return new "length" }
Kleine Tests:
String[] a = {"0", "1", "2", "3", "4"}; removeItems(a, 0, 3, 4); // remove 0-th, 3-rd and 4-th items System.out.println(Arrays.asList(a)); // [1, 2, null, null, null]
In Ihrer Aufgabe können Sie zuerst das Array scannen, um Positionen von "a" zu erfassen, und dann aufrufen
removeItems()
.quelle
Etwas an dem Erstellen einer Liste, das dann entfernt und dann wieder zu einem Array zurückkehrt, scheint mir falsch zu sein. Noch nicht getestet, aber ich denke, dass das Folgende besser abschneiden wird. Ja, ich optimiere wahrscheinlich übermäßig vor.
boolean [] deleteItem = new boolean[arr.length]; int size=0; for(int i=0;i<arr.length;i==){ if(arr[i].equals("a")){ deleteItem[i]=true; } else{ deleteItem[i]=false; size++; } } String[] newArr=new String[size]; int index=0; for(int i=0;i<arr.length;i++){ if(!deleteItem[i]){ newArr[index++]=arr[i]; } }
quelle
Mir ist klar, dass dies ein sehr alter Beitrag ist, aber einige der Antworten hier haben mir geholfen, also hier ist meine Tuppence 'ha'pennys Wert!
Ich hatte eine ganze Weile Mühe, dies zum Laufen zu bringen, bevor ich feststellte, dass die Größe des Arrays, in das ich zurückschreibe, geändert werden musste, es sei denn, die an der vorgenommenen Änderungen
ArrayList
lassen die Listengröße unverändert.Wenn das
ArrayList
, das Sie ändern, mehr oder weniger Elemente enthält als es begonnen hat, verursacht die ZeileList.toArray()
eine Ausnahme. Sie benötigen also etwas wieList.toArray(new String[] {})
oderList.toArray(new String[0])
, um ein Array mit der neuen (richtigen) Größe zu erstellen.Klingt jetzt offensichtlich, wo ich es weiß. Nicht so offensichtlich für einen Android / Java-Neuling, der sich mit neuen und unbekannten Codekonstrukten auseinandersetzt, und nicht offensichtlich aus einigen der früheren Beiträge hier, also wollte ich diesen Punkt nur für alle anderen klar machen, die sich stundenlang am Kopf kratzen, wie ich es war !
quelle
Hier gibt es viele Antworten - das Problem ist meines Erachtens, dass Sie nicht gesagt haben, WARUM Sie ein Array anstelle einer Sammlung verwenden. Lassen Sie mich daher einige Gründe vorschlagen und welche Lösungen zutreffen würden (die meisten Lösungen) wurden hier bereits in anderen Fragen beantwortet, damit ich nicht zu sehr ins Detail gehe):
Grund: Sie wussten nicht, dass das Sammlungspaket vorhanden ist, oder haben ihm nicht vertraut
Lösung: Verwenden Sie eine Sammlung.
Wenn Sie in der Mitte hinzufügen / löschen möchten, verwenden Sie eine LinkedList. Wenn Sie sich wirklich Sorgen um die Größe machen oder häufig mitten in der Sammlung indizieren, verwenden Sie eine ArrayList. Beide sollten Löschvorgänge haben.
Grund: Sie sind besorgt über die Größe oder möchten die Speicherzuweisung steuern
Lösung: Verwenden Sie eine ArrayList mit einer bestimmten Anfangsgröße.
Eine ArrayList ist einfach ein Array, das sich selbst erweitern kann, dies muss jedoch nicht immer der Fall sein. Das Hinzufügen / Entfernen von Elementen ist sehr klug. Wenn Sie jedoch eine Menge in der Mitte einfügen / entfernen, verwenden Sie eine LinkedList.
Grund: Sie haben ein Array, das hereinkommt und ein Array, das ausgeht. Sie möchten also ein Array bearbeiten
Lösung: Konvertieren Sie es in eine ArrayList, löschen Sie das Element und konvertieren Sie es zurück
Grund: Sie denken, Sie können besseren Code schreiben, wenn Sie es selbst tun
Lösung: Sie können kein Array oder keine verknüpfte Liste verwenden.
Grund: Dies ist eine Klassenzuweisung und Sie sind nicht erlaubt oder Sie haben aus irgendeinem Grund keinen Zugriff auf die Sammlungs-APIs
Annahme: Das neue Array muss die richtige "Größe" haben.
Lösung: Scannen Sie das Array nach passenden Elementen und zählen Sie diese. Erstellen Sie ein neues Array mit der richtigen Größe (Originalgröße - Anzahl der Übereinstimmungen). Verwenden Sie System.arraycopy wiederholt, um jede Gruppe von Elementen, die Sie behalten möchten, in Ihr neues Array zu kopieren. Wenn dies eine Klassenzuweisung ist und Sie System.arraycopy nicht verwenden können, kopieren Sie sie einfach einzeln von Hand in einer Schleife, aber tun Sie dies niemals im Produktionscode, da dies viel langsamer ist. (Diese Lösungen werden beide in anderen Antworten detailliert beschrieben.)
Grund: Sie müssen Bare Metal laufen lassen
Annahme: Sie dürfen nicht unnötig Speicherplatz zuweisen oder zu lange dauern
Annahme: Sie verfolgen die im Array verwendete Größe (Länge) separat, da Sie sonst Ihr Array für Löschungen / Einfügungen neu zuweisen müssten.
Ein Beispiel dafür, warum Sie dies tun möchten: Ein einzelnes Array von Grundelementen (sagen wir int-Werte) nimmt einen erheblichen Teil Ihres RAMs ein - wie 50%! Eine ArrayList würde diese in eine Liste von Zeigern auf Integer-Objekte zwingen, die ein paar Mal so viel Speicher benötigen würden.
Lösung: Durchlaufen Sie Ihr Array. Wenn Sie ein zu entfernendes Element finden (nennen wir es Element n), kopieren Sie mit System.arraycopy das Ende des Arrays über das "gelöschte" Element (Quelle und Ziel sind dasselbe Array) ist klug genug, um die Kopie in die richtige Richtung zu erstellen, damit sich der Speicher nicht selbst überschreibt:
Sie möchten wahrscheinlich schlauer sein, wenn Sie mehr als ein Element gleichzeitig löschen. Sie würden nur den Bereich zwischen einem "Match" und dem nächsten verschieben und nicht den gesamten Schwanz. Vermeiden Sie wie immer, einen Block zweimal zu verschieben.
In diesem letzten Fall müssen Sie die Arbeit unbedingt selbst erledigen, und die Verwendung von System.arraycopy ist wirklich die einzige Möglichkeit, da dies die bestmögliche Methode zum Verschieben des Speichers für Ihre Computerarchitektur ist - sie sollte um ein Vielfaches schneller sein als jeder Code, den Sie vernünftigerweise selbst schreiben könnten.
quelle
Anfängliches Array
int[] array = {5,6,51,4,3,2};
Wenn Sie 51 entfernen möchten, dh Index 2, verwenden Sie Folgendes
for(int i = 2; i < array.length -1; i++){ array[i] = array[i + 1]; }
quelle
BEARBEITEN:
Der Punkt mit den Nullen im Array wurde gelöscht. Entschuldigung für meine Kommentare.
Original:
Ähm ... die Linie
Ersetzt alle Lücken im Array, in denen das entfernte Element war, durch null . Dies kann gefährlich sein , da die Elemente entfernt werden, die Länge des Arrays jedoch gleich bleibt!
Wenn Sie dies vermeiden möchten, verwenden Sie ein neues Array als Parameter für toArray (). Wenn Sie removeAll nicht verwenden möchten, ist ein Set eine Alternative:
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" }; System.out.println(Arrays.toString(array)); Set<String> asSet = new HashSet<String>(Arrays.asList(array)); asSet.remove("a"); array = asSet.toArray(new String[] {}); System.out.println(Arrays.toString(array));
Gibt:
Wo wie die aktuell akzeptierte Antwort von Chris Yester Young ausgibt:
[a, bc, dc, a, ef] [bc, dc, ef, null, ef]
mit dem Code
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" }; System.out.println(Arrays.toString(array)); List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array); System.out.println(Arrays.toString(array));
ohne dass Nullwerte zurückbleiben.
quelle
Mein kleiner Beitrag zu diesem Problem.
public class DeleteElementFromArray { public static String foo[] = {"a","cc","a","dd"}; public static String search = "a"; public static void main(String[] args) { long stop = 0; long time = 0; long start = 0; System.out.println("Searched value in Array is: "+search); System.out.println("foo length before is: "+foo.length); for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);} System.out.println("=============================================================="); start = System.nanoTime(); foo = removeElementfromArray(search, foo); stop = System.nanoTime(); time = stop - start; System.out.println("Equal search took in nano seconds = "+time); System.out.println("=========================================================="); for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);} } public static String[] removeElementfromArray( String toSearchfor, String arr[] ){ int i = 0; int t = 0; String tmp1[] = new String[arr.length]; for(;i<arr.length;i++){ if(arr[i] == toSearchfor){ i++; } tmp1[t] = arr[i]; t++; } String tmp2[] = new String[arr.length-t]; System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length); arr = tmp2; tmp1 = null; tmp2 = null; return arr; }
}}
quelle
Es kommt darauf an, was du mit "entfernen" meinst? Ein Array ist ein Konstrukt mit fester Größe. Sie können die Anzahl der darin enthaltenen Elemente nicht ändern. Sie können also entweder a) ein neues, kürzeres Array ohne die Elemente erstellen, die Sie nicht möchten, oder b) die Einträge, die Sie nicht möchten, etwas zuweisen, das ihren Status "leer" anzeigt; normalerweise null, wenn Sie nicht mit Grundelementen arbeiten.
Erstellen Sie im ersten Fall eine Liste aus dem Array, entfernen Sie die Elemente und erstellen Sie ein neues Array aus der Liste. Wenn die Leistung wichtig ist, durchlaufen Sie das Array und weisen Sie alle Elemente zu, die nicht zu einer Liste entfernt werden sollen, und erstellen Sie dann ein neues Array aus der Liste. Im zweiten Fall gehen Sie einfach durch und weisen den Array-Einträgen null zu.
quelle
Arrgh, ich kann den Code nicht richtig anzeigen lassen. Entschuldigung, ich habe es geschafft. Entschuldigung nochmal, ich glaube nicht, dass ich die Frage richtig gelesen habe.
String foo[] = {"a","cc","a","dd"}, remove = "a"; boolean gaps[] = new boolean[foo.length]; int newlength = 0; for (int c = 0; c<foo.length; c++) { if (foo[c].equals(remove)) { gaps[c] = true; newlength++; } else gaps[c] = false; System.out.println(foo[c]); } String newString[] = new String[newlength]; System.out.println(""); for (int c1=0, c2=0; c1<foo.length; c1++) { if (!gaps[c1]) { newString[c2] = foo[c1]; System.out.println(newString[c2]); c2++; } }
quelle
Kopiert alle Elemente außer dem mit dem Index i:
if(i == 0){ System.arraycopy(edges, 1, copyEdge, 0, edges.length -1 ); }else{ System.arraycopy(edges, 0, copyEdge, 0, i ); System.arraycopy(edges, i+1, copyEdge, i, edges.length - (i+1) ); }
quelle
In einer Reihe von Strings wie
String name = 'abcdeafbde' // könnte wie String name = 'aa bb cde aa f bb de' sein
Ich baue die folgende Klasse
class clearname{ def parts def tv public def str = '' String name clearname(String name){ this.name = name this.parts = this.name.split(" ") this.tv = this.parts.size() } public String cleared(){ int i int k int j=0 for(i=0;i<tv;i++){ for(k=0;k<tv;k++){ if(this.parts[k] == this.parts[i] && k!=i){ this.parts[k] = ''; j++ } } } def str = '' for(i=0;i<tv;i++){ if(this.parts[i]!='') this.str += this.parts[i].trim()+' ' } return this.str }} return new clearname(name).cleared()
dieses Ergebnis erhalten
abcdef
hoffe, dieser Code hilft jedem Grüße
quelle
Wenn es nicht auf die Reihenfolge der Elemente ankommt. Sie können zwischen den Elementen foo [x] und foo [0] wechseln und dann foo.drop (1) aufrufen.
foo.drop(n)
Entfernt (n) erste Elemente aus dem Array.Ich denke, dies ist der einfachste und ressourceneffizienteste Weg.
PS :
indexOf
kann auf viele Arten implementiert werden, dies ist meine Version.Integer indexOf(String[] arr, String value){ for(Integer i = 0 ; i < arr.length; i++ ) if(arr[i] == value) return i; // return the index of the element return -1 // otherwise -1 } while (true) { Integer i; i = indexOf(foo,"a") if (i == -1) break; foo[i] = foo[0]; // preserve foo[0] foo.drop(1); }
quelle
Verwenden:
list.removeAll(...); //post what char you need in the ... section
quelle
Weisen Sie den Array-Positionen null zu.
quelle