Для массива из n объектов, допустим, это массив строк со следующими значениями:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Что мне нужно сделать, чтобы удалить / удалить все строки / объекты, равные «a» в массиве?
Для массива из n объектов, допустим, это массив строк со следующими значениями:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Что мне нужно сделать, чтобы удалить / удалить все строки / объекты, равные «a» в массиве?
Ответы:
[Если вам нужен готовый код, прокрутите до моего «Edit3» (после вырезания). Остальное здесь для потомков.]
Чтобы конкретизировать идею Дастмана :
List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array);
Изменить: Я сейчас , используя
Arrays.asList
вместоCollections.singleton
: синглтон ограничивается одной записи, в то время какasList
подход позволяет добавить другие строки , чтобы отфильтровать позднее:Arrays.asList("a", "b", "c")
.Edit2: Приведенный выше подход сохраняет тот же массив (поэтому массив все еще имеет ту же длину); элемент после последнего устанавливается равным нулю. Если вы хотите, чтобы размер нового массива был точно таким, как требуется, используйте вместо этого:
array = list.toArray(new String[0]);
Edit3: если вы часто используете этот код в одном классе, вы можете подумать о добавлении этого в свой класс:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Тогда функция становится:
List<String> list = new ArrayList<>(); Collections.addAll(list, array); list.removeAll(Arrays.asList("a")); array = list.toArray(EMPTY_STRING_ARRAY);
Тогда это перестанет засорять вашу кучу бесполезными массивами пустых строк, которые в противном случае редактировались бы
new
каждый раз при вызове вашей функции.Предложение циничного человека (см. комментарии) также поможет с засорением кучи, и для справедливости я должен его упомянуть:
array = list.toArray(new String[list.size()]);
Я предпочитаю свой подход, потому что может быть легче
size()
указать неправильный размер (например, вызвать неправильный список).источник
Альтернатива в Java 8:
String[] filteredArray = Arrays.stream(array) .filter(e -> !e.equals(foo)).toArray(String[]::new);
источник
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
будет достаточно.Сделайте
List
из массиваArrays.asList()
и вызовитеremove()
все соответствующие элементы. Затем вызовитеtoArray()
«Список», чтобы снова превратить его в массив.Не очень производительный, но если вы его правильно инкапсулируете, вы всегда сможете сделать что-то быстрее позже.
источник
Arrays.asList()
не поддерживаетremove()
. Так этот ответ полностью неверен? Похоже, что некоторые комментарии были удалены, поэтому я не знаю, обсуждалось ли это.Вы всегда можете:
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);
источник
Вы можете использовать внешнюю библиотеку:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Он находится в проекте Apache Commons Lang http://commons.apache.org/lang/
источник
ArrayUtils.removeElement(boolean[] array, boolean element)
тоже очень полезно.См. Код ниже
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings)); a.remove(i); strings = new String[a.size()]; a.toArray(strings);
источник
Если вам нужно удалить несколько элементов из массива, не преобразовывая его и
List
не создавая дополнительный массив, вы можете сделать это за O (n), независимо от количества удаляемых элементов.Здесь
a
исходный массив,int... r
отдельные упорядоченные индексы (позиции) удаляемых элементов: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" }
Небольшое тестирование:
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]
В вашей задаче вы можете сначала сканировать массив, чтобы собрать позиции «а», а затем позвонить
removeItems()
.источник
Здесь есть много ответов - проблема, как я вижу, в том, что вы не сказали, ПОЧЕМУ вы используете массив вместо коллекции, поэтому позвольте мне предложить пару причин и какие решения будут применяться (большинство решений здесь уже были даны ответы на другие вопросы, поэтому я не буду вдаваться в подробности):
причина: вы не знали о существовании пакета сбора или не доверяли ему
Решение: используйте коллекцию.
Если вы планируете добавлять / удалять из середины, используйте LinkedList. Если вас действительно беспокоит размер или вы часто индексируете прямо в середине коллекции, используйте ArrayList. Оба они должны иметь операции удаления.
причина: вы обеспокоены размером или хотите контролировать распределение памяти
Решение: используйте ArrayList с определенным начальным размером.
ArrayList - это просто массив, который может расширяться, но это не всегда нужно делать. Будет очень разумно добавлять / удалять элементы, но, опять же, если вы вставляете / удаляете ЛОТ из середины, используйте LinkedList.
причина: у вас есть массив, входящий и выходящий массив, поэтому вы хотите работать с массивом
Решение: преобразовать его в ArrayList, удалить элемент и преобразовать обратно
причина: вы думаете, что можете написать лучший код, если сделаете это сами
Решение: вы не можете использовать массив или связанный список.
причина: это назначение класса, и вам не разрешено или у вас нет доступа к API коллекции по какой-то причине
предположение: вам нужно, чтобы новый массив был правильного «размера»
Решение: просканируйте массив на предмет совпадающих элементов и посчитайте их. Создайте новый массив правильного размера (исходный размер - количество совпадений). используйте System.arraycopy несколько раз, чтобы скопировать каждую группу элементов, которые вы хотите сохранить, в новый массив. Если это назначение класса и вы не можете использовать System.arraycopy, просто копируйте их по одному вручную в цикле, но никогда не делайте этого в производственном коде, потому что это намного медленнее. (Эти решения подробно описаны в других ответах)
причина: вам нужно запускать голый металл
предположение: вы НЕ ДОЛЖНЫ выделять пространство без необходимости или занимать слишком много времени
предположение: вы отслеживаете размер, используемый в массиве (длину) отдельно, потому что в противном случае вам пришлось бы перераспределять массив для удаления / вставки.
Пример того, почему вы можете захотеть это сделать: один массив примитивов (скажем, значения int) занимает значительную часть вашего барана - например, 50%! ArrayList включит их в список указателей на объекты Integer, которые будут использовать в несколько раз больше памяти.
Решение: выполните итерацию по вашему массиву и всякий раз, когда вы найдете элемент, который нужно удалить (назовем его элементом n), используйте System.arraycopy, чтобы скопировать хвост массива поверх «удаленного» элемента (Источник и Назначение - это один и тот же массив) - это достаточно умен, чтобы делать копию в правильном направлении, чтобы память не перезаписывалась:
Вы, вероятно, захотите быть умнее этого, если удаляете более одного элемента за раз. Вы должны перемещать только область между одним «совпадением» и другим, а не весь хвост, и, как всегда, избегайте перемещения любого фрагмента дважды.
В этом последнем случае вы обязательно должны выполнить работу самостоятельно, и использование System.arraycopy - действительно единственный способ сделать это, поскольку он будет выбирать лучший способ перемещения памяти для вашей компьютерной архитектуры - это должно быть во много раз быстрее. чем любой код, который вы могли бы написать самостоятельно.
источник
Что-то в том, чтобы составить список, затем удалить, а затем вернуться в массив, кажется мне неправильным. Не тестировал, но я думаю, что следующие будут работать лучше. Да, я, наверное, излишне заранее оптимизирую.
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]; } }
источник
Я понимаю, что это очень старый пост, но некоторые ответы здесь помогли мне, так что вот моя цена!
Я долго изо всех сил пытался заставить это работать, прежде чем подумать, что массив, в который я записываю, должен быть изменен, если только изменения, внесенные в список, не
ArrayList
оставляют размер списка неизменным.Если
ArrayList
модифицируемый вами элемент будет иметь большее или меньшее количество элементов, чем было в начале, строкаList.toArray()
вызовет исключение, поэтому вам нужно что-то вродеList.toArray(new String[] {})
илиList.toArray(new String[0])
для создания массива с новым (правильным) размером.Теперь, когда я это знаю, это звучит очевидно. Это не так очевидно для новичка в Android / Java, который разбирается в новых и незнакомых конструкциях кода, и не очевидно из некоторых из предыдущих публикаций здесь, поэтому просто хотел прояснить этот момент для всех, кто часами ломает голову, как я !
источник
Исходный массив
int[] array = {5,6,51,4,3,2};
если вы хотите удалить 51, который является индексом 2, используйте следующие
for(int i = 2; i < array.length -1; i++){ array[i] = array[i + 1]; }
источник
РЕДАКТИРОВАТЬ:
Точка с нулями в массиве очищена. Извините за мои комментарии.
Оригинал:
Эм ... линия
заменяет все пробелы в массиве, где был удаленный элемент, на null . Это может быть опасно , потому что элементы удаляются, но длина массива остается прежней!
Если вы хотите избежать этого, используйте новый массив в качестве параметра для toArray (). Если вы не хотите использовать removeAll, альтернативой будет Set:
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));
Дает:
Где, как текущий принятый ответ от Криса Йестера Янга, выводится:
[a, bc, dc, a, ef] [bc, dc, ef, null, ef]
с кодом
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));
без каких-либо оставленных нулевых значений.
источник
Мой небольшой вклад в эту проблему.
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; }
}
источник
Это зависит от того, что вы подразумеваете под «удалением»? Массив - это конструкция фиксированного размера - вы не можете изменить количество элементов в нем. Таким образом, вы можете либо а) создать новый, более короткий массив без элементов, которые вам не нужны, или б) назначить записи, которые вы не хотите, чему-то, что указывает на их «пустой» статус; обычно null, если вы не работаете с примитивами.
В первом случае создайте список из массива, удалите элементы и создайте новый массив из списка. Если производительность важна, перебирайте массив, назначая любые элементы, которые не следует удалять, в список, а затем создайте новый массив из списка. Во втором случае просто пройдите и присвойте пустым записям массива.
источник
Arrgh, я не могу заставить код отображаться правильно. Извините, у меня все заработало. Еще раз извините, я не думаю, что правильно прочитал вопрос.
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++; } }
источник
Скопирует все элементы, кроме элемента с индексом 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) ); }
источник
В массиве строк типа
String name = 'abcdeafbde' // может быть как String name = 'aa bb cde aa f bb de'
Строю следующий класс
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()
получить этот результат
abcdef
надеюсь, что этот код поможет кому-нибудь С уважением
источник
Если не имеет значения порядок элементов. вы можете переключаться между элементами foo [x] и foo [0], а затем вызывать foo.drop (1).
foo.drop(n)
удаляет (n) первых элементов из массива.Думаю, это самый простой и ресурсосберегающий способ сделать это.
PS :
indexOf
можно реализовать разными способами, это моя версия.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); }
источник
Использование:
list.removeAll(...); //post what char you need in the ... section
источник
Присвойте нулевое значение расположениям массива.
источник