Biorąc pod uwagę tablicę n Obiektów, powiedzmy, że jest to tablica ciągów i ma następujące wartości:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Co muszę zrobić, aby usunąć / usunąć wszystkie ciągi / obiekty równe „a” w tablicy?
java
arrays
data-structures
data-manipulation
ramayac
źródło
źródło
Odpowiedzi:
[Jeśli potrzebujesz kodu gotowego do użycia, przejdź do mojego „Edit3” (po wycięciu). Reszta jest tutaj dla potomności.]
Aby zrealizować pomysł Dustmana :
List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array);
Edit: Jestem teraz używając
Arrays.asList
zamiastCollections.singleton
: Singleton jest ograniczona do jednego wejścia, natomiastasList
podejście pozwala na dodawanie innych ciągów odfiltrować później:Arrays.asList("a", "b", "c")
.Edit2: powyższe podejście zachowuje tę samą tablicę (więc tablica ma nadal tę samą długość); element po ostatnim jest ustawiony na null. Jeśli chcesz, aby nowa tablica miała dokładnie taki rozmiar, jak jest to wymagane, użyj tego:
array = list.toArray(new String[0]);
Edycja3: Jeśli często używasz tego kodu w tej samej klasie, możesz rozważyć dodanie go do swojej klasy:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Wtedy funkcja staje się:
List<String> list = new ArrayList<>(); Collections.addAll(list, array); list.removeAll(Arrays.asList("a")); array = list.toArray(EMPTY_STRING_ARRAY);
Spowoduje to, że przestaniesz zaśmiecać stertę bezużytecznymi pustymi tablicami łańcuchowymi, które w przeciwnym razie byłyby edytowane za
new
każdym razem, gdy wywoływana jest funkcja.cyniczna sugestia (patrz komentarze) pomoże również w zaśmiecaniu sterty i dla uczciwości powinienem o tym wspomnieć:
array = list.toArray(new String[list.size()]);
Wolę moje podejście, ponieważ może być łatwiej uzyskać błędny rozmiar (np. Wywołanie
size()
niewłaściwej listy).źródło
Alternatywa w Javie 8:
String[] filteredArray = Arrays.stream(array) .filter(e -> !e.equals(foo)).toArray(String[]::new);
źródło
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
byłoby wystarczające.Utwórz a
List
z tablicy za pomocąArrays.asList()
i wywołajremove()
wszystkie odpowiednie elementy. Następnie wywołajtoArray()
„Listę”, aby ponownie utworzyć tablicę.Niezbyt wydajne, ale jeśli odpowiednio je hermetyzujesz, zawsze możesz zrobić coś szybciej później.
źródło
Arrays.asList()
nie obsługujeremove()
. Czy więc ta odpowiedź jest całkowicie nieprawidłowa? Wygląda na to, że niektóre komentarze zostały usunięte, więc nie wiem, czy było to omawiane.Zawsze możesz:
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);
źródło
Możesz skorzystać z biblioteki zewnętrznej:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Jest w projekcie Apache Commons Lang http://commons.apache.org/lang/
źródło
ArrayUtils.removeElement(boolean[] array, boolean element)
jest również bardzo przydatna.Zobacz kod poniżej
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings)); a.remove(i); strings = new String[a.size()]; a.toArray(strings);
źródło
Jeśli chcesz usunąć wiele elementów z tablicy bez konwertowania jej
List
ani tworzenia dodatkowej tablicy, możesz to zrobić w O (n) niezależnie od liczby elementów do usunięcia.Oto
a
tablica początkowa,int... r
to różne uporządkowane indeksy (pozycje) elementów do usunięcia: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" }
Małe testy:
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]
W swoim zadaniu możesz najpierw przeskanować tablicę, aby zebrać pozycje „a”, a następnie wywołać
removeItems()
.źródło
Odpowiedzi jest wiele - problem, jak widzę, polega na tym, że nie powiedziałeś DLACZEGO używasz tablicy zamiast zbioru, więc pozwól, że zasugeruję kilka powodów i które rozwiązania będą miały zastosowanie (większość rozwiązań na które udzielono już odpowiedzi w innych pytaniach, więc nie będę wchodził w zbyt wiele szczegółów):
powód: nie wiedziałeś, że pakiet kolekcji istnieje lub nie ufałeś mu
rozwiązanie: użyj kolekcji.
Jeśli planujesz dodawać / usuwać od środka, użyj LinkedList. Jeśli naprawdę martwisz się o rozmiar lub często indeksujesz bezpośrednio w środku kolekcji, użyj ArrayList. Oba powinny mieć operacje usuwania.
powód: obawiasz się rozmiaru lub chcesz mieć kontrolę nad alokacją pamięci
rozwiązanie: użyj ArrayList o określonym rozmiarze początkowym.
ArrayList to po prostu tablica, która może się rozszerzać, ale nie zawsze musi to robić. Będzie bardzo sprytnie dodawać / usuwać elementy, ale ponownie, jeśli wstawiasz / usuwasz DUŻO ze środka, użyj LinkedList.
powód: masz tablicę przychodzącą i tablicę wychodzącą - więc chcesz operować na tablicy
rozwiązanie: przekonwertuj go na ArrayList, usuń element i przekonwertuj go z powrotem
powód: myślisz, że możesz napisać lepszy kod, jeśli zrobisz to sam
rozwiązanie: nie możesz, użyj listy Array lub Linked.
powód: to jest zadanie klasowe i nie masz pozwolenia lub z jakiegoś powodu nie masz dostępu do zbioru api
założenie: nowa tablica musi mieć odpowiedni „rozmiar”
rozwiązanie: przeskanuj tablicę pod kątem pasujących elementów i policz je. Utwórz nową tablicę o odpowiednim rozmiarze (rozmiar oryginalny - liczba dopasowań). użyj System.arraycopy wielokrotnie, aby skopiować każdą grupę elementów, które chcesz zachować, do nowej tablicy. Jeśli jest to przypisanie do klasy i nie możesz użyć System.arraycopy, po prostu skopiuj je pojedynczo ręcznie w pętli, ale nigdy nie rób tego w kodzie produkcyjnym, ponieważ jest znacznie wolniejszy. (Te rozwiązania są szczegółowo opisane w innych odpowiedziach)
powód: musisz uruchomić goły metal
założenie: NIE WOLNO niepotrzebnie przydzielać miejsca ani zajmować zbyt dużo czasu
założenie: Śledzisz rozmiar używany w tablicy (długość) oddzielnie, ponieważ w przeciwnym razie musiałbyś ponownie przydzielić tablicę do usuwania / wstawiania.
Przykład tego, dlaczego warto to zrobić: pojedyncza tablica prymitywów (powiedzmy wartości int) zajmuje znaczną część pamięci RAM - na przykład 50%! ArrayList wymusiłoby to na liście wskaźników do obiektów typu Integer, które zużywałyby kilka razy więcej pamięci.
rozwiązanie: powtórz swoją tablicę i za każdym razem, gdy znajdziesz element do usunięcia (nazwijmy go elementem n), użyj System.arraycopy, aby skopiować koniec tablicy na element „usunięty” (źródło i miejsce docelowe to ta sama tablica) - to jest wystarczająco inteligentny, aby wykonać kopię we właściwym kierunku, aby pamięć się nie nadpisała:
Prawdopodobnie będziesz chciał być mądrzejszy, jeśli usuwasz więcej niż jeden element naraz. Przesuwałbyś tylko obszar między jednym „dopasowaniem” a następnym, a nie całym ogonem i, jak zawsze, unikałbyś dwukrotnego przesuwania fragmentu.
W tym ostatnim przypadku absolutnie musisz wykonać tę pracę samodzielnie, a użycie System.arraycopy jest naprawdę jedynym sposobem, aby to zrobić, ponieważ wybierze najlepszy możliwy sposób przeniesienia pamięci dla architektury komputera - powinno być wielokrotnie szybsze niż jakikolwiek kod, który mógłbyś napisać samodzielnie.
źródło
Coś w tworzeniu listy, a następnie usuwaniu i wracaniu do tablicy wydaje mi się złe. Nie testowałem, ale myślę, że poniższe będą działać lepiej. Tak, prawdopodobnie zbytnio optymalizuję wstępnie.
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]; } }
źródło
Zdaję sobie sprawę, że to bardzo stary post, ale niektóre odpowiedzi mi pomogły, więc oto moja wartość za dwa pensy!
Zmagałem się z tym, aby to działało przez dłuższy czas, zanim przekręciłem, że tablica, do której piszę, musi zostać zmieniona, chyba że zmiany wprowadzone w liście
ArrayList
pozostawiają niezmieniony rozmiar.Jeśli to
ArrayList
, co modyfikujesz, kończy się na większej lub mniejszej liczbie elementów niż na początku, liniaList.toArray()
spowoduje wyjątek, więc potrzebujesz czegoś takiego jakList.toArray(new String[] {})
lubList.toArray(new String[0])
, aby utworzyć tablicę z nowym (prawidłowym) rozmiarem.Teraz, kiedy już to wiem, wydaje się oczywiste. Nie jest to takie oczywiste dla nowicjusza z Androidem / Javą, który zmaga się z nowymi i nieznanymi konstrukcjami kodu i nie jest oczywiste z niektórych wcześniejszych postów tutaj, więc chciałem tylko, aby ta kwestia była naprawdę jasna dla każdego, kto drapie się po głowie godzinami, tak jak ja !
źródło
Tablica początkowa
int[] array = {5,6,51,4,3,2};
jeśli chcesz usunąć 51, czyli indeks 2, użyj następującego
for(int i = 2; i < array.length -1; i++){ array[i] = array[i + 1]; }
źródło
EDYTOWAĆ:
Punkt z wartościami null w tablicy został wyczyszczony. Przepraszam za moje komentarze.
Oryginalny:
Ehm ... linia
zastępuje wszystkie luki w tablicy, w której usunięty element miał wartość null . Może to być niebezpieczne , ponieważ elementy są usuwane, ale długość tablicy pozostaje taka sama!
Jeśli chcesz tego uniknąć, użyj nowego parametru Array jako parametru toArray (). Jeśli nie chcesz używać removeAll, alternatywą byłby zestaw:
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));
Daje:
Gdzie jako obecnie zaakceptowana odpowiedź od Chrisa Yestera Younga:
[a, bc, dc, a, ef] [bc, dc, ef, null, ef]
z kodem
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));
bez pozostawionych wartości null.
źródło
Mój mały wkład w ten 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; }
}
źródło
To zależy od tego, co masz na myśli mówiąc „usuń”? Tablica jest konstrukcją o stałym rozmiarze - nie możesz zmienić liczby zawartych w niej elementów. Możesz więc albo a) utworzyć nową, krótszą tablicę bez elementów, których nie chcesz lub b) przypisać wpisy, których nie chcesz, do czegoś, co wskazuje na ich status „pusty”; zwykle null, jeśli nie pracujesz z prymitywami.
W pierwszym przypadku utwórz Listę z tablicy, usuń elementy i utwórz nową tablicę z listy. Jeśli wydajność jest ważna, iteruj po tablicy, przypisując wszystkie elementy, które nie powinny być usuwane z listy, a następnie utwórz nową tablicę z listy. W drugim przypadku po prostu przejdź i przypisz null do wpisów tablicy.
źródło
Arrgh, nie mogę uzyskać poprawnego wyświetlenia kodu. Przepraszam, udało mi się. Przepraszam jeszcze raz, nie sądzę, żebym poprawnie przeczytał pytanie.
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++; } }
źródło
Skopiuje wszystkie elementy oprócz tego z indeksem 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) ); }
źródło
W tablicy ciągów, takich jak
String name = 'abcdeafbde' // może wyglądać jak String name = 'aa bb cde aa f bb de'
Buduję następującą klasę
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()
uzyskanie tego wyniku
Alfabet
Mam nadzieję, że ten kod pomoże każdemu. Pozdrawiam
źródło
Jeśli nie ma znaczenia kolejność elementów. możesz przełączać się między elementami foo [x] i foo [0], a następnie wywołać foo.drop (1).
foo.drop(n)
usuwa (n) pierwsze elementy z tablicy.Myślę, że jest to najprostszy i efektywny pod względem zasobów sposób.
PS :
indexOf
można zaimplementować na wiele sposobów, to jest moja wersja.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); }
źródło
Posługiwać się:
list.removeAll(...); //post what char you need in the ... section
źródło
Przypisz null do lokalizacji tablicy.
źródło