n 개의 객체 의 배열이 주어 졌을 때, 이것이 strings 의 배열이고 다음과 같은 값을 가지고 있다고 가정 해 봅시다 .
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
배열에서 "a" 와 같은 모든 문자열 / 객체를 삭제 / 제거하려면 어떻게해야 합니까?
n 개의 객체 의 배열이 주어 졌을 때, 이것이 strings 의 배열이고 다음과 같은 값을 가지고 있다고 가정 해 봅시다 .
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
함수가 호출 될 때마다 처리 되는 쓸모없는 빈 문자열 배열로 힙을 버리는 것을 중지합니다 .
cynicalman의 제안 (댓글 참조)은 힙 쓰레기 처리에도 도움이 될 것이며 공정성을 위해 언급해야합니다.
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)
매우 유용합니다.
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는 단순히 자체적으로 확장 할 수있는 배열이지만 항상 그렇게 할 필요는 없습니다. 항목을 추가 / 제거하는 것은 매우 현명하지만 중간에서 LOT를 삽입 / 제거하는 경우에는 LinkedList를 사용하십시오.
이유 : 배열이 들어오고 나가는 배열이 있으므로 배열에서 작업하고 싶습니다.
솔루션 : 그것을 ArrayList로 변환하고, 항목을 삭제하고 다시 변환하십시오.
이유 : 스스로하면 더 나은 코드를 작성할 수 있다고 생각합니다.
솔루션 : 할 수 없습니다, 배열 또는 연결된 목록을 사용할 수 있습니다.
이유 : 이것은 수업 과제이며 허용되지 않거나 어떤 이유로 컬렉션 API에 액세스 할 수 없습니다.
가정 : 새 배열이 올바른 "크기"여야합니다.
솔루션 : 배열에서 일치하는 항목을 스캔하고 개수를 세십시오. 올바른 크기 (원래 크기-일치 수)의 새 배열을 만듭니다. System.arraycopy를 반복해서 사용하여 유지하려는 각 항목 그룹을 새 배열에 복사합니다. 이것이 클래스 할당이고 System.arraycopy를 사용할 수없는 경우 루프에서 한 번에 하나씩 수동으로 복사하지만 훨씬 느리기 때문에 프로덕션 코드에서는이 작업을 수행하지 마십시오. (이 솔루션은 모두 다른 답변에 자세히 설명되어 있습니다)
이유 : 베어 메탈을 실행해야합니다.
가정 : 불필요하게 공간을 할당하거나 너무 오래 걸리지 않아야합니다.
가정 : 배열에 사용 된 크기 (길이)를 별도로 추적하고 있습니다. 그렇지 않으면 삭제 / 삽입을 위해 배열을 재 할당해야하기 때문입니다.
이 작업을 수행하려는 이유의 예 : 단일 기본 요소 배열 (int 값이라고 가정 해 보겠습니다)이 숫양의 상당 부분을 차지합니다 (예 : 50 %)! ArrayList는 이들을 메모리 양의 몇 배를 사용하는 Integer 객체에 대한 포인터 목록으로 강제합니다.
솔루션 : 배열을 반복하고 제거 할 요소를 찾을 때마다 (요소 n이라고합시다) System.arraycopy를 사용하여 "삭제 된"요소 위에 배열의 꼬리를 복사합니다 (소스와 대상은 동일한 배열). 메모리가 자체를 덮어 쓰지 않도록 올바른 방향으로 복사 할 수있을만큼 똑똑합니다.
System.arraycopy (ary, n + 1, ary, n, 길이 -n) 길이--;
한 번에 둘 이상의 요소를 삭제하는 경우 이보다 더 똑똑해지기를 원할 것입니다. 전체 꼬리가 아니라 하나의 "일치"와 다음 "일치"사이에서만 영역을 이동하고 항상 그렇듯이 청크를 두 번 이동하지 마십시오.
이 마지막 경우에는 반드시 직접 작업을 수행해야하며 System.arraycopy를 사용하는 것은 컴퓨터 아키텍처를 위해 메모리를 이동하는 가장 좋은 방법을 선택할 것이기 때문에 실제로 수행 할 수있는 유일한 방법입니다. 합리적으로 직접 작성할 수있는 코드보다
편집하다:
배열에 널이있는 지점이 지워졌습니다. 내 의견에 대해 죄송합니다.
실물:
음 ... 라인
array = list.toArray(array);
제거 된 요소가 null 인 배열의 모든 간격을 바꿉니다 . 요소가 제거 되었기 때문에 위험 할 수 있지만 배열의 길이는 동일하게 유지됩니다!
이를 방지하려면 toArray ()의 매개 변수로 새 Array를 사용하십시오. 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;
}
}
"제거"의 의미에 따라 다릅니다. 배열은 크기가 고정 된 구조입니다. 배열의 요소 수를 변경할 수 없습니다. 따라서 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++;
}
}
같은 문자열 배열에서
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) 개를 제거합니다.
나는 이것이 가장 간단하고 자원 효율적인 방법이라고 생각합니다.
추신 : 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);
}