Учитывая массив объектов 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" (после вырезания). Остальное здесь для потомков.]
Извлечь Идею Dustman:
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Изменить: теперь я использую Arrays.asList
вместо Collections.singleton
: singleton ограничен одной записью, тогда как метод asList
позволяет вам добавлять другие строки для фильтрации позже: Arrays.asList("a", "b", "c")
.
Edit2: вышеприведенный подход сохраняет тот же массив (так что массив остается той же длины); элемент после последнего устанавливается равным null. Если вы хотите, чтобы новый массив был как можно более точным, используйте вместо этого:
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
ed при каждом вызове функции.
cynicalman suggestion (см. комментарии) также поможет с завалением кучи, и для справедливости я должен упомянуть это:
array = list.toArray(new String[list.size()]);
Я предпочитаю свой подход, потому что может быть проще получить явный размер неправильно (например, вызывать size()
в неправильном списке).
Альтернатива в Java 8:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
Сделайте List
из массива с Arrays.asList()
и вызовите remove()
для всех соответствующих элементов. Затем вызовите toArray()
в "List", чтобы снова вернуться в массив.
Не очень впечатляюще, но если вы инкапсулируете его правильно, вы всегда можете сделать что-то более быстрое.
Вы всегда можете сделать:
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/
См. код ниже
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]
В вашей задаче вы можете сначала просмотреть массив, чтобы собрать позиции "a", а затем вызвать removeItems()
.
Что-то о том, чтобы сделать список, а затем удалить, а затем вернуться к массиву, кажется мне неправильным. Не тестировали, но я думаю, что следующее будет работать лучше. Да, я, вероятно, необоснованно заранее оптимизирую.
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, который справляется с новыми и незнакомыми конструкциями кода и не очевиден из некоторых более ранних сообщений здесь, поэтому просто хотел, чтобы этот пункт был действительно понятен для кого-то еще, царапающего их головы часами, как я был
Здесь много ответов - проблема в том, что вы не сказали, ПОЧЕМУ вы используете массив вместо коллекции, поэтому позвольте мне предложить пару причин и какие решения будут применяться (Most о решениях уже были даны ответы на другие вопросы здесь, поэтому я не буду вдаваться в подробности):
причина: вы не знали, что пакет коллекции существует или не доверял ему
Решение: используйте коллекцию.
Если вы планируете добавлять/удалять из середины, используйте LinkedList. Если вы действительно обеспокоены размером или часто индексируете прямо в середину коллекции, используйте ArrayList. Обе из них должны иметь операции удаления.
причина: вы обеспокоены размером или хотите контролировать распределение памяти
: используйте ArrayList с определенным начальным размером.
ArrayList - это просто массив, который может расширяться, но это не всегда нужно делать. Будет очень полезно добавлять/удалять элементы, но опять же, если вы вставляете/удаляете LOT из середины, используйте LinkedList.
причина: у вас есть массив, в который входит массив, и вы хотите работать с массивом
: преобразовать его в ArrayList, удалить элемент и преобразовать его
причина: вы думаете, что можете написать лучший код, если вы сделаете это самостоятельно
: вы не можете использовать список Array или Linked.
причина: это назначение класса, и вы не разрешены или у вас нет доступа к коллекции apis по какой-либо причине
Предположение: новый массив должен быть правильным "размером"
решение: Сканирование массива для сопоставления элементов и подсчета их. Создайте новый массив правильного размера (исходный размер - количество совпадений). используйте System.arraycopy для копирования каждой группы элементов, которые вы хотите сохранить в новом массиве. Если это назначение класса, и вы не можете использовать System.arraycopy, просто скопируйте их по одному вручную в цикле, но никогда не делайте этого в производственном коде, потому что он намного медленнее. (Эти решения подробно описаны в других ответах)
причина: вам нужно запустить bare metal
: вы НЕ ДОЛЖНЫ распределять пространство без необходимости или слишком долго
Предположение: вы отслеживаете размер, используемый в массиве (длина) отдельно, потому что в противном случае вам придется перераспределять ваш массив для удаления/вставки.
Пример того, почему вы, возможно, захотите сделать это: один массив примитивов (Let say int values) занимает значительную часть вашего барана - например, 50%! ArrayList заставит их перечислить указатели на объекты Integer, которые будут использовать несколько раз этот объем памяти.
: Итерируйте по вашему массиву и всякий раз, когда вы обнаружите элемент для удаления (пусть его вызывает элемент n), используйте System.arraycopy для копирования хвоста массива над "удаленным" элементом (Source и Destination - это тот же массив) - Это достаточно умно, чтобы сделать копию в правильном направлении, чтобы память не перезаписывала себя:
System.arraycopy(ary, n+1, ary, n, length-n) length--;
Вероятно, вы захотите стать более умным, если вы удалите более одного элемента за раз. Вы только перемещали бы область между одним "совпадением" и следующим, а не всем хвостом, и, как всегда, избегайте перемещать любой фрагмент дважды.
В этом последнем случае вы абсолютно должны сами выполнить эту работу, и использование System.arraycopy - это единственный способ сделать это, поскольку он собирается выбрать наилучший возможный способ перемещения памяти для вашей компьютерной архитектуры - это должно быть во много раз быстрее, чем любой код, который вы могли бы разумно написать себе.
EDIT:
Точка с нулями в массиве очищена. Извините за мои комментарии.
Оригинал:
Ehm... строка
array = list.toArray(array);
заменяет все пробелы в массиве, где удаленный элемент был с null. Это может быть опасно, поскольку элементы удаляются, но длина массива остается неизменной!
Если вы хотите этого избежать, используйте новый параметр Array для параметра 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]
[dc, ef, bc]
Где в качестве текущего принятого ответа от Chris Yester Young выходят:
[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;
}
}
Начальный массив
int[] array = {5,6,51,4,3,2};
если вы хотите удалить 51, который является индексом 2, используйте следующее
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
Астро, я не могу правильно отобразить код. Извините, я заработал. Извините, я не думаю, что правильно прочитал вопрос.
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++;
}
}
Это зависит от того, что вы подразумеваете под "удалением"? Массив - это конструкция с фиксированным размером - вы не можете изменить количество элементов в нем. Таким образом, вы можете: a) создать новый, более короткий массив без элементов, которые вам не нужны, или b) назначить записи, которые вы не хотите, чтобы указать их "пустой" статус; обычно null, если вы не работаете с примитивами.
В первом случае создайте список из массива, удалите его и создайте новый массив из списка. Если производительность важна, перебирайте массив, назначая любые элементы, которые не следует удалять в список, а затем создайте новый массив из списка. Во втором случае просто перейдите и присвойте значение NULL элементам.
Скопирует все элементы, кроме одного с индексом 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 d e'
Я строю следующий класс
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);
}
class sd
{
public static void main(String[ ] args)
{
System.out.println("Search and Delete");
int key;
System.out.println("Enter the length of array:");
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int numbers[]=new int[n];
int i = 0;
boolean found = false;
System.out.println("Enter the elements in Array :");
for ( i = 0; i < numbers.length; i++)
{
numbers[i]=in.nextInt();
}
System.out.println("The elements in Array are:");
for ( i = 0; i < numbers.length; i++)
{
System.out.println(numbers[i]);
}
System.out.println("Enter the element to be searched:");
key=in.nextInt();
for ( i = 0; i < numbers.length; i++)
{
if (numbers[ i ] == key)
{
found = true;
break;
}
}
if (found)
{
System.out.println("Found " + key + " at index " + i + ".");
numbers[i]=0;//haven't deleted the element in array
System.out.println("After Deletion:");
for ( i = 0; i < numbers.length; i++)
{
if (numbers[ i ]!=0)
{ //it skips displaying element in array
System.out.println(numbers[i]);
}
}
}
else
{
System.out.println(key + "is not in this array.");
}
}
}//Sorry.. if there are mistakes.
Использование:
list.removeAll(...);
//post what char you need in the ... section
Назначьте нуль ячейкам массива.