Dada una matriz de n objetos, digamos que es una matriz de cadenas y tiene los siguientes valores:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
¿Qué tengo que hacer para eliminar / eliminar todas las cadenas / objetos iguales a "a" en la matriz?
java
arrays
data-structures
data-manipulation
ramayac
fuente
fuente
Respuestas:
[Si desea algún código listo para usar, desplácese hasta mi "Edit3" (después del corte). El resto está aquí para la posteridad.]
Para desarrollar la idea de Dustman :
List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array);
Edit: Ahora estoy usando
Arrays.asList
en lugar deCollections.singleton
: Singleton se limita a una entrada, mientras que elasList
enfoque le permite añadir otras cadenas para filtrar más adelante:Arrays.asList("a", "b", "c")
.Edit2: el enfoque anterior conserva la misma matriz (por lo que la matriz sigue teniendo la misma longitud); el elemento después del último se establece en nulo. Si desea una nueva matriz de tamaño exactamente como se requiere, use esto en su lugar:
array = list.toArray(new String[0]);
Edit3: si usa este código con frecuencia en la misma clase, es posible que desee considerar agregar esto a su clase:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Entonces la función se convierte en:
List<String> list = new ArrayList<>(); Collections.addAll(list, array); list.removeAll(Arrays.asList("a")); array = list.toArray(EMPTY_STRING_ARRAY);
Esto dejará de ensuciar su montón con matrices de cadenas vacías inútiles que de otro modo se editarían
new
cada vez que se llame a su función.La sugerencia de Cynicalman (ver comentarios) también ayudará con el montón de basura, y para ser justos, debería mencionarlo:
array = list.toArray(new String[list.size()]);
Prefiero mi enfoque, porque puede ser más fácil obtener el tamaño explícito incorrecto (por ejemplo, llamar
size()
a la lista incorrecta).fuente
Una alternativa en Java 8:
String[] filteredArray = Arrays.stream(array) .filter(e -> !e.equals(foo)).toArray(String[]::new);
fuente
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
lo que sería suficiente.Haga un
List
fuera de la matriz conArrays.asList()
y llameremove()
a todos los elementos apropiados. Luego, llametoArray()
a la 'Lista' para volver a formar una matriz.No es muy eficaz, pero si lo encapsula correctamente, siempre puede hacer algo más rápido más adelante.
fuente
Arrays.asList()
no es compatibleremove()
. Entonces, ¿esta respuesta es completamente inválida? Parece que tal vez se eliminaron algunos comentarios, así que no sé si esto se discutió.Siempre puedes hacer:
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);
fuente
Puede utilizar una biblioteca externa:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Está en el proyecto Apache Commons Lang http://commons.apache.org/lang/
fuente
ArrayUtils.removeElement(boolean[] array, boolean element)
también es muy útil.Ver código a continuación
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings)); a.remove(i); strings = new String[a.size()]; a.toArray(strings);
fuente
Si necesita eliminar varios elementos de la matriz sin convertirlos
List
ni crear una matriz adicional, puede hacerlo en O (n) sin depender del recuento de elementos para eliminar.Aquí,
a
es la matriz inicial,int... r
hay distintos índices ordenados (posiciones) de elementos para eliminar: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" }
Pequeñas pruebas:
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]
En su tarea, primero puede escanear la matriz para recopilar las posiciones de "a", luego llamar
removeItems()
.fuente
Algo sobre hacer una lista, luego eliminarlo y luego volver a una matriz me parece incorrecto. No lo he probado, pero creo que lo siguiente funcionará mejor. Sí, probablemente estoy pre-optimizando indebidamente.
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]; } }
fuente
Me doy cuenta de que esta es una publicación muy antigua, pero algunas de las respuestas aquí me ayudaron, ¡así que aquí está mi tuppence 'un penique!
Luché para que esto funcionara durante bastante tiempo antes de cambiar el tamaño de la matriz en la que estoy escribiendo de nuevo, a menos que los cambios realizados en
ArrayList
la lista dejen el tamaño de la lista sin cambios.Si el
ArrayList
que está modificando termina con más o menos elementos de los que comenzó, la líneaList.toArray()
causará una excepción, por lo que necesita algo comoList.toArray(new String[] {})
oList.toArray(new String[0])
para crear una matriz con el nuevo tamaño (correcto).Suena obvio ahora que lo sé. No es tan obvio para un novato de Android / Java que se está familiarizando con construcciones de código nuevas y desconocidas y no es obvio en algunas de las publicaciones anteriores aquí, así que solo quería dejar este punto muy claro para cualquier otra persona que se rasca la cabeza durante horas como yo. !
fuente
Hay muchas respuestas aquí; el problema, tal como lo veo, es que no dijo POR QUÉ está usando una matriz en lugar de una colección, así que permítame sugerir un par de razones y qué soluciones se aplicarían (la mayoría de las soluciones ya han sido respondidas en otras preguntas aquí, por lo que no entraré en demasiados detalles):
motivo: no sabía que existía el paquete de colección o no confiaba en él
solución: Utilice una colección.
Si planea agregar / eliminar desde el medio, use una LinkedList. Si está realmente preocupado por el tamaño o, a menudo, indexa directamente en el medio de la colección, use una ArrayList. Ambos deberían tener operaciones de eliminación.
motivo: le preocupa el tamaño o desea controlar la asignación de memoria
solución: use una ArrayList con un tamaño inicial específico.
Una ArrayList es simplemente una matriz que se puede expandir, pero no siempre es necesario que lo haga. Será muy inteligente agregar / eliminar elementos, pero nuevamente si está insertando / eliminando MUCHO del medio, use una LinkedList.
motivo: tiene una matriz entrando y una matriz saliendo, por lo que desea operar en una matriz
solución: conviértalo en un ArrayList, elimine el elemento y conviértalo de nuevo
motivo: cree que puede escribir un código mejor si lo hace usted mismo
solución: no puede, use una matriz o una lista vinculada.
motivo: esta es una tarea de clase y no está permitido o no tiene acceso a las apis de la colección por algún motivo
suposición: necesita que la nueva matriz tenga el "tamaño" correcto
solución: escanee la matriz en busca de elementos coincidentes y cuéntelos. Cree una nueva matriz del tamaño correcto (tamaño original - número de coincidencias). use System.arraycopy repetidamente para copiar cada grupo de elementos que desea retener en su nueva matriz. Si esta es una asignación de clase y no puede usar System.arraycopy, simplemente cópielos uno a la vez a mano en un bucle, pero nunca lo haga en el código de producción porque es mucho más lento. (Estas soluciones se detallan en otras respuestas)
motivo: necesitas ejecutar bare metal
suposición: no DEBE asignar espacio innecesariamente o tomar demasiado tiempo
suposición: está rastreando el tamaño utilizado en la matriz (longitud) por separado porque, de lo contrario, tendría que reasignar su matriz para eliminaciones / inserciones.
Un ejemplo de por qué es posible que desee hacer esto: una sola matriz de primitivas (digamos valores int) está tomando una parte significativa de su RAM, ¡como el 50%! Un ArrayList los forzaría en una lista de punteros a objetos Integer que usarían unas pocas veces esa cantidad de memoria.
solución: Itere sobre su matriz y cada vez que encuentre un elemento para eliminar (llamémoslo elemento n), use System.arraycopy para copiar la cola de la matriz sobre el elemento "eliminado" (la fuente y el destino son la misma matriz): es lo suficientemente inteligente como para hacer la copia en la dirección correcta para que la memoria no se sobrescriba a sí misma:
Probablemente querrá ser más inteligente que esto si está eliminando más de un elemento a la vez. Solo movería el área entre una "coincidencia" y la siguiente en lugar de toda la cola y, como siempre, evite mover cualquier trozo dos veces.
En este último caso, debe hacer el trabajo usted mismo, y usar System.arraycopy es realmente la única forma de hacerlo, ya que elegirá la mejor forma posible de mover la memoria para la arquitectura de su computadora; debería ser muchas veces más rápido que cualquier código que pueda escribir usted mismo.
fuente
Matriz inicial
int[] array = {5,6,51,4,3,2};
si desea eliminar 51 que es el índice 2, use lo siguiente
for(int i = 2; i < array.length -1; i++){ array[i] = array[i + 1]; }
fuente
EDITAR:
Se borró el punto con los nulos en la matriz. Perdón por mis comentarios.
Original:
Ehm ... la línea
reemplaza todos los espacios en la matriz donde el elemento eliminado ha estado con nulo . Esto puede ser peligroso , porque los elementos se eliminan, ¡pero la longitud de la matriz sigue siendo la misma!
Si desea evitar esto, use una nueva matriz como parámetro para toArray (). Si no desea utilizar removeAll, un conjunto sería una alternativa:
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));
Da:
Donde, como la respuesta aceptada actual de Chris Yester Young produce:
[a, bc, dc, a, ef] [bc, dc, ef, null, ef]
con el codigo
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));
sin ningún valor nulo dejado atrás.
fuente
Mi pequeña contribución a este problema.
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; }
}
fuente
¿Depende de lo que quieras decir con "eliminar"? Una matriz es una construcción de tamaño fijo; no puede cambiar la cantidad de elementos que contiene. Por lo tanto, puede a) crear una nueva matriz más corta sin los elementos que no desea ob) asignar las entradas que no desea a algo que indique su estado "vacío"; generalmente es nulo si no está trabajando con primitivas.
En el primer caso, cree una lista de la matriz, elimine los elementos y cree una nueva matriz de la lista. Si el rendimiento es importante, repita la matriz asignando los elementos que no deben eliminarse a una lista y luego cree una nueva matriz a partir de la lista. En el segundo caso, simplemente revise y asigne un valor nulo a las entradas de la matriz.
fuente
Arrgh, no puedo hacer que el código aparezca correctamente. Lo siento, lo tengo funcionando. Lo siento de nuevo, no creo haber leído bien la pregunta.
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++; } }
fuente
Copiará todos los elementos excepto el que tiene el índice 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) ); }
fuente
En una matriz de cadenas como
String name = 'abcdeafbde' // podría ser como String name = 'aa bb cde aa f bb de'
Construyo la siguiente clase
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()
obteniendo este resultado
a B C D e F
Espero que este código ayude a todos.
fuente
Si no importa el orden de los elementos. puede intercambiar entre los elementos foo [x] y foo [0], luego llamar a foo.drop (1).
foo.drop(n)
elimina (n) primeros elementos de la matriz.Supongo que esta es la forma más sencilla y eficiente de hacerlo.
PD :
indexOf
se puede implementar de muchas formas, esta es mi versión.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); }
fuente
Utilizar:
list.removeAll(...); //post what char you need in the ... section
fuente
Asignar nulo a las ubicaciones de la matriz.
fuente