문제

주어진 배열 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함수가 호출될 때마다 ed.

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

나는 이것이 매우 오래된 게시물이라는 것을 알고 있지만 여기에 있는 답변 중 일부가 나에게 도움이 되었기 때문에 여기에 내 tuppence' ha'penny의 가치가 있습니다!

나는 내가 다시 쓰고 있는 배열의 크기를 조정해야 한다는 사실을 깨닫기 전에 꽤 오랫동안 이 작업을 수행하는 데 어려움을 겪었습니다. ArrayList 목록 크기를 변경하지 않고 그대로 둡니다.

만약 ArrayList 수정하려는 요소는 처음보다 더 많거나 적은 요소로 끝납니다. List.toArray() 예외가 발생하므로 다음과 같은 것이 필요합니다. List.toArray(new String[] {}) 또는 List.toArray(new String[0]) 새로운 (올바른) 크기의 배열을 생성합니다.

이제 알았으니 당연한 것 같습니다.새롭고 익숙하지 않은 코드 구성을 이해하는 Android/Java 초보자에게는 그리 명확하지 않으며 여기에 있는 이전 게시물 중 일부에서도 분명하지 않습니다. 그래서 저처럼 몇 시간 동안 머리를 긁적거리는 다른 사람들을 위해 이 점을 정말 명확하게 설명하고 싶었습니다. !

여기에는 많은 답변이 있습니다. 제가 보기에 문제는 컬렉션 대신 배열을 사용하는 이유를 말하지 않았다는 것입니다. 따라서 몇 가지 이유와 적용할 솔루션을 제안하겠습니다(대부분의 솔루션은 여기의 다른 질문에서는 이미 답변을 받았으므로 너무 자세히 설명하지는 않겠습니다.)

이유:컬렉션 패키지가 존재하는지 몰랐거나 신뢰하지 않았습니다.

해결책:컬렉션을 사용하세요.

중간부터 추가/삭제할 계획이라면 LinkedList를 사용하세요.크기가 정말 걱정되거나 컬렉션 중간에 바로 인덱스를 추가하는 경우 ArrayList를 사용하세요.두 가지 모두 삭제 작업이 있어야 합니다.

이유:크기가 걱정되거나 메모리 할당을 제어하고 싶습니다.

해결책:특정 초기 크기를 가진 ArrayList를 사용하십시오.

ArrayList는 단순히 자체적으로 확장할 수 있는 배열이지만 항상 확장할 필요는 없습니다.항목을 추가/제거하는 것은 매우 현명하지만, 중간에서 많은 것을 삽입/제거하는 경우에는 LinkedList를 사용하십시오.

이유:들어오는 배열과 나가는 배열이 있으므로 배열에서 작업을 수행하려고 합니다.

해결책:ArrayList로 변환하고 항목을 삭제한 후 다시 변환합니다.

이유:스스로 작성하면 더 나은 코드를 작성할 수 있다고 생각합니다.

해결책:그렇지 않으면 배열 또는 연결 목록을 사용하십시오.

이유:이것은 수업 과제이며 허용되지 않거나 어떤 이유로 컬렉션 API에 액세스할 수 없습니다.

추정:올바른 "크기"가 되려면 새 배열이 필요합니다.

해결책:일치하는 항목이 있는지 배열을 스캔하고 개수를 계산합니다.올바른 크기(원래 크기 - 일치 항목 수)의 새 배열을 만듭니다.System.arraycopy를 반복적으로 사용하여 유지하려는 각 항목 그룹을 새 배열에 복사하십시오.이것이 클래스 할당이고 System.arraycopy를 사용할 수 없는 경우 루프에서 한 번에 하나씩 직접 복사하면 됩니다. 그러나 프로덕션 코드에서는 훨씬 느리기 때문에 이 작업을 수행하지 마십시오.(이 솔루션은 모두 다른 답변에 자세히 설명되어 있습니다)

이유:베어메탈을 실행해야 합니다.

추정:불필요하게 공간을 할당하거나 너무 오래 걸리면 안 됩니다.

추정:그렇지 않으면 삭제/삽입을 위해 배열을 재할당해야 하기 때문에 배열에 사용된 크기(길이)를 별도로 추적하고 있습니다.

이 작업을 수행하려는 이유에 대한 예:단일 프리미티브 배열(int 값이라고 가정)이 램의 상당 부분을 차지합니다(예: 50%)!ArrayList는 이를 메모리 양의 몇 배를 사용하는 Integer 객체에 대한 포인터 목록으로 강제합니다.

해결책:배열을 반복하고 제거할 요소를 찾을 때마다(요소 n이라고 부르겠습니다) System.arraycopy를 사용하여 "삭제된" 요소 위에 배열의 꼬리를 복사합니다(소스와 대상은 동일한 배열입니다)--똑똑합니다. 올바른 방향으로 복사를 수행하기에 충분하므로 메모리 자체를 덮어쓰지 않습니다.

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

한 번에 두 개 이상의 요소를 삭제하는 경우 이보다 더 똑똑해지고 싶을 것입니다.전체 꼬리가 아닌 하나의 "일치"와 다음 사이의 영역만 이동하고 항상 그렇듯이 청크를 두 번 이동하지 마십시오.

이 마지막 경우에는 작업을 반드시 직접 수행해야 하며 System.arraycopy를 사용하는 것이 컴퓨터 아키텍처에 맞게 메모리를 이동할 수 있는 최선의 방법을 선택하므로 이 작업을 수행할 수 있는 유일한 방법입니다. 몇 배 더 빨라야 합니다. 스스로 합리적으로 작성할 수 있는 어떤 코드보다 말이죠.

편집하다:

배열에서 null이 있는 지점이 지워졌습니다.내 의견에 대해 죄송합니다.

원래의:

음...라인

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]

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));

null 값이 남지 않습니다.

이 문제에 대한 나의 작은 기여.

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

인덱스 2인 51을 제거하려면 다음을 사용하십시오.

 for(int i = 2; i < array.length -1; i++){
    array[i] = array[i + 1];
  }

"제거"의 의미에 따라 다릅니다.배열은 고정된 크기 구조이므로 배열의 요소 수를 변경할 수 없습니다.따라서 a) 원하지 않는 요소 없이 새롭고 짧은 배열을 생성하거나 b) '비어 있음' 상태를 나타내는 항목에 원하지 않는 항목을 할당할 수 있습니다.기본 요소로 작업하지 않는 경우 일반적으로 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) );
            }

다음과 같은 문자열 배열에서

문자열 이름 = 'a b c d e a f b d e' // 다음과 같을 수 있습니다. 문자열 이름 = '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