Вопрос

Задан массив из n Объекты, допустим, это массив строк, и он имеет следующие значения:

foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";

Что мне нужно сделать, чтобы удалить все строки / объекты, равные "а" в массиве?

Это было полезно?

Решение

[Если вам нужен готовый к использованию код, пожалуйста, перейдите к моему "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").

Редактировать 2:Приведенный выше подход сохраняет тот же массив (таким образом, массив остается той же длины).;элементу после последнего присваивается значение null.Если вы хотите новое размер массива точно соответствует требуемому, используйте это вместо:

array = list.toArray(new String[0]);

Редактировать 3:Если вы часто используете этот код в одном и том же классе, возможно, вы захотите добавить его в свой класс:

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редактируйте каждый раз, когда вызывается ваша функция.

предложение cynicalman (см. Комментарии) также поможет с засорением кучи, и справедливости ради я должен упомянуть об этом:

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() в "Списке", чтобы снова преобразовать обратно в массив.

Не очень производительный, но если вы правильно инкапсулируете его, то позже всегда сможете сделать что-то более быстрое.

Ты всегда можешь это сделать:

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, который только начинает разбираться с новыми и незнакомыми конструкциями кода, и не очевидно из некоторых предыдущих постов здесь, поэтому просто хотел прояснить этот момент для всех, кто еще часами ломает голову, как я!

Здесь много ответов - проблема, как я вижу, в том, что вы не сказали, ПОЧЕМУ вы используете массив вместо коллекции, поэтому позвольте мне предложить пару причин и какие решения будут применимы (на большинство решений уже были даны ответы в других вопросах здесь, поэтому я не буду вдаваться в подробности):

Причина:Вы не знали о существовании пакета сбора данных или не доверяли ему

решение:Используйте коллекцию.

Если вы планируете добавлять / удалять из середины, используйте LinkedList.Если вы действительно беспокоитесь о размере или часто индексируете прямо в середине коллекции, используйте ArrayList.Оба они должны содержать операции удаления.

Причина:Вас беспокоит размер или вы хотите контролировать распределение памяти

решение:Используйте ArrayList с определенным начальным размером.

ArrayList - это просто массив, который может расширяться сам по себе, но ему не всегда нужно это делать.Это будет очень разумно при добавлении / удалении элементов, но опять же, если вы вставляете / удаляете МНОГО из середины, используйте LinkedList.

Причина:У вас есть входящий массив и выходящий массив - итак, вы хотите оперировать с массивом

решение:Преобразуйте его в ArrayList, удалите элемент и преобразуйте его обратно

Причина:Вы думаете, что сможете написать лучший код, если сделаете это сами

решение:вы не можете использовать Массив или Связанный список.

Причина:это назначение класса, и по какой-то причине вам не разрешено или у вас нет доступа к API-интерфейсам collection

предположение:Вам нужно, чтобы новый массив был правильного "размера".

решение:Просканируйте массив на наличие совпадающих элементов и подсчитайте их.Создайте новый массив правильного размера (исходный размер - количество совпадений).используйте System.arraycopy повторно, чтобы скопировать каждую группу элементов, которые вы хотите сохранить, в ваш новый массив.Если это назначение класса, и вы не можете использовать System.arraycopy, просто скопируйте их по одному вручную в цикле, но никогда не делайте этого в производственном коде, потому что это намного медленнее.(Оба этих решения подробно описаны в других ответах)

Причина:вам нужно использовать голый металл

предположение:вы НЕ ДОЛЖНЫ выделять пространство без необходимости или занимать слишком много времени

предположение:Вы отслеживаете размер, используемый в массиве (длину), отдельно, потому что в противном случае вам пришлось бы перераспределять ваш массив для удаления / вставки.

Пример того, почему вы, возможно, захотите это сделать:один массив примитивов (скажем, значений int) занимает значительную часть вашей оперативной памяти - примерно 50%!ArrayList принудительно преобразовал бы их в список указателей на целочисленные объекты, которые использовали бы в несколько раз больший объем памяти.

решение:Выполните итерацию по вашему массиву и всякий раз, когда вы находите элемент для удаления (назовем его элементом n), используйте System.arraycopy, чтобы скопировать конец массива поверх "удаленного" элемента (источник и назначение - это один и тот же массив) - он достаточно умен, чтобы выполнить копирование в правильном направлении, чтобы память не перезаписывала себя:

 System.arraycopy(ary, n+1, ary, n, length-n) 
 length--;

Вероятно, вам захочется быть умнее, если вы удаляете более одного элемента одновременно.Вы бы перемещали только область между одной "спичкой" и следующей, а не весь хвост и, как всегда, избегали бы перемещения любого фрагмента дважды.

В этом последнем случае вам абсолютно необходимо выполнить всю работу самостоятельно, и использование System.arraycopy - действительно единственный способ сделать это, поскольку он собирается выбрать наилучший возможный способ перемещения памяти для вашей компьютерной архитектуры - это должно быть во много раз быстрее, чем любой код, который вы могли бы разумно написать самостоятельно.

Редактировать:

Точка с нулевыми значениями в массиве была очищена.Извините за мои комментарии.

Оригинал:

Ehm...линия

array = list.toArray(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]

Где в качестве текущего принятого ответа от Криса Йестера Янга выводится:

[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];
  }

Это зависит от того, что вы подразумеваете под "удалить"?Массив - это конструкция фиксированного размера - вы не можете изменить количество элементов в нем.Таким образом, вы можете либо а) создать новый, более короткий массив без элементов, которые вам не нужны, либо б) присвоить ненужным записям что-то, что указывает на их статус "пусто";обычно null, если вы не работаете с примитивами.

В первом случае создайте список из массива, удалите элементы и создайте новый массив из списка.Если важна производительность, выполните итерацию по массиву, назначив все элементы, которые не следует удалять, в список, а затем создайте новый массив из списка.Во втором случае просто пройдите и присвоите null элементам массива.

Арррх, я не могу заставить код отображаться корректно.Извини, у меня все получилось.Еще раз извините, мне кажется, я неправильно прочитал вопрос.

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 = 'a b c d e a f b d e' // может быть как String name = 'aa bb c d e 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()

получение этого результата

a b c d e f

надеюсь, этот код кому-нибудь поможет С уважением

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

Присвоите null расположениям массива.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top