Etant donné un tableau de n Objects, supposons que c'est un tableau de chaînes , et qu'il a les valeurs suivantes:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Que dois-je faire pour supprimer/supprimer toutes les chaînes/objets égaux à "a" dans le tableau?
[Si vous voulez du code prêt à l'emploi, s'il vous plaît faites défiler jusqu'à mon "Edit3" (après la coupe). Le reste est là pour la postérité.]
Pour étoffer l'idée de Dustman :
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Edit: J'utilise maintenant Arrays.asList
au lieu de Collections.singleton
: le singleton est limité à une entrée, alors que l'approche asList
vous permet d'ajouter d'autres chaînes à filtrer ultérieurement: Arrays.asList("a", "b", "c")
.
Edit2: L'approche ci-dessus conserve le même tableau (le tableau a donc toujours la même longueur); l'élément après le dernier est défini sur null. Si vous voulez un tableau new de la taille exacte, utilisez plutôt ceci:
array = list.toArray(new String[0]);
Edit3: Si vous utilisez fréquemment ce code dans la même classe, vous pouvez envisager de l’ajouter à votre classe:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Alors la fonction devient:
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
Cela évitera alors de surcharger votre segment de mémoire avec des tableaux de chaînes vides inutiles qui, autrement, seraient new
ed à chaque appel de votre fonction.
la suggestion de cynicalman (voir les commentaires) aidera également à éliminer les déchets, et pour être juste, je devrais le mentionner:
array = list.toArray(new String[list.size()]);
Je préfère mon approche, car il peut être plus facile de se tromper de taille explicite (par exemple, en appelant size()
sur la mauvaise liste).
Une alternative en Java 8:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
Créez une List
du tableau avec Arrays.asList()
et appelez remove()
sur tous les éléments appropriés. Appelez ensuite toArray()
dans la liste pour revenir dans un tableau.
Pas très performant, mais si vous l’encapsulez correctement, vous pourrez toujours faire quelque chose de plus vite plus tard.
Vous pouvez toujours faire:
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);
Vous pouvez utiliser une bibliothèque externe:
org.Apache.commons.lang.ArrayUtils.remove(Java.lang.Object[] array, int index)
C'est dans le projet Apache Commons Lang http://commons.Apache.org/lang/
Voir le code ci-dessous
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
Si vous devez supprimer plusieurs éléments d'un tableau sans le convertir en List
ni créer de tableau supplémentaire, vous pouvez le faire dans O(n) en fonction du nombre d'éléments à supprimer.
Ici, a
est le tableau initial, int... r
sont des index ordonnés distincts (positions) des éléments à supprimer:
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"
}
Petit test:
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]
Dans votre tâche, vous pouvez d’abord scanner un tableau pour collecter les positions de "a", puis appeler removeItems()
.
Quelque chose à propos de la liste puis de l'enlever puis de revenir à un tableau me semble erroné. N'a pas été testé, mais je pense que ce qui suit sera plus performant. Oui, je suis probablement en train de pré-optimiser indûment.
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];
}
}
Je réalise que c'est un très vieux billet, mais certaines des réponses ici m'ont aidé, alors voici la valeur de ma tuppence 'ha'penny!
J'ai eu du mal à obtenir que cela fonctionne pendant un bon bout de temps avant de penser que le tableau dans lequel je suis en train d'écrire devait être redimensionné, à moins que les modifications apportées à la variable ArrayList
ne modifient pas la taille de la liste.
Si la ArrayList
que vous modifiez se termine avec un nombre d'éléments supérieur ou inférieur au nombre initial, la ligne List.toArray()
provoquera une exception. Vous avez donc besoin de quelque chose comme List.toArray(new String[] {})
ou List.toArray(new String[0])
pour créer un tableau avec la nouvelle taille (correcte).
Cela semble évident maintenant que je le sais. Pas si évident pour un débutant sous Android/Java qui est en train de se familiariser avec des constructions de code nouvelles et inconnues et comme cela n’est pas évident dans certains posts précédents, je voulais donc que ce point soit vraiment clair pour quiconque se gratter la tête pendant des heures comme j’étais !
MODIFIER:
Le point avec les valeurs NULL dans le tableau a été effacé. Désolé pour mes commentaires.
Original:
Euh ... la ligne
array = list.toArray(array);
remplace tous les espaces dans le tableau où l'élément supprimé a été avec null . Cela peut être dangereux , car les éléments sont supprimés, mais la longueur du tableau reste la même!
Si vous voulez éviter cela, utilisez un nouveau tableau comme paramètre pour toArray (). Si vous ne voulez pas utiliser removeAll, un ensemble serait une alternative:
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));
Donne:
[a, bc, dc, a, ef]
[dc, ef, bc]
Où comme réponse actuelle acceptée de Chris Yester Young produit:
[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]
avec le code
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));
sans aucune valeur nulle laissée derrière.
Il y a beaucoup de réponses ici - le problème car je vois que c'est que vous n'avez pas dit POURQUOI vous utilisez un tableau au lieu d'une collection, laissez-moi vous suggérer quelques raisons et les solutions qui s'appliqueraient (La plupart des solutions déjà été répondu dans d'autres questions ici, donc je ne vais pas trop entrer dans les détails):
raison: vous ne saviez pas que le paquet de collecte existait ou ne vous y fiez pas
solution: Utilisez une collection.
Si vous envisagez d’ajouter ou de supprimer du milieu, utilisez une LinkedList. Si vous êtes vraiment préoccupé par la taille ou indexez souvent au milieu de la collection, utilisez un ArrayList. Ces deux doivent avoir des opérations de suppression.
raison: votre taille vous préoccupe ou vous souhaitez contrôler l'allocation de mémoire
solution: Utilisez un ArrayList avec une taille initiale spécifique.
Un ArrayList est simplement un tableau qui peut se développer, mais ce n'est pas toujours nécessaire. Il sera très judicieux d'ajouter/supprimer des éléments, mais encore une fois, si vous insérez/supprimez un LOT au milieu, utilisez une LinkedList.
raison: vous avez un tableau entrant et un tableau sortant - vous voulez donc opérer sur un tableau
solution: convertissez-le en une liste de tableaux, supprimez l'élément et reconvertissez-le
raison: vous pensez que vous pouvez écrire un meilleur code si vous le faites vous-même
solution: vous ne pouvez pas, utiliser un tableau ou une liste liée.
raison: il s'agit d'une tâche de classe et vous n'êtes pas autorisé ou vous n'avez pas accès aux API de collection pour une raison quelconque
hypothèse: le nouveau tableau doit avoir la "taille" correcte
solution: Analysez le tableau pour rechercher les éléments correspondants et comptez-les. Créez un nouveau tableau de la taille correcte (taille d'origine - nombre de correspondances). utilisez plusieurs fois System.arraycopy pour copier chaque groupe d'éléments que vous souhaitez conserver dans votre nouveau tableau. S'il s'agit d'une affectation de classe et que vous ne pouvez pas utiliser System.arraycopy, copiez-les une à la fois à la main dans une boucle, mais ne le faites jamais dans le code de production car il est beaucoup plus lent. (Ces solutions sont détaillées dans d'autres réponses)
raison: vous devez utiliser du métal nu
hypothèse: vous ne devez PAS allouer d'espace inutilement ni prendre trop de temps
hypothèse: vous suivez la taille utilisée dans le tableau (longueur) séparément car sinon, vous devrez réaffecter votre tableau aux suppressions/insertions.
Voici un exemple de pourquoi vous voudrez peut-être faire cela: un seul tableau de primitives (disons des valeurs int) prend une grande partie de votre bélier - comme 50%! Un ArrayList les forcerait dans une liste de pointeurs sur les objets Integer qui utiliseraient une quantité de mémoire égale à quelques fois.
solution: Itérer sur votre tableau et chaque fois que vous trouvez un élément à supprimer (appelons-le élément n), utilisez System.arraycopy pour copier la queue du tableau sur l'élément "supprimé" (Source et Destination sont le même tableau) - il est assez intelligent pour faire la copie dans le bon sens pour que la mémoire ne s’écrase pas elle-même:
System.arraycopy (ary, n + 1, ary, n, length-n) longueur--;
Vous voudrez probablement être plus intelligent que cela si vous supprimez plusieurs éléments à la fois. Vous ne feriez que déplacer la zone entre les deux parties plutôt que la queue entière et, comme toujours, évitez de déplacer deux fois un morceau.
Dans ce dernier cas, vous devez absolument faire le travail vous-même, et utiliser System.arraycopy est vraiment le seul moyen de le faire, car il va choisir le meilleur moyen de déplacer éventuellement de la mémoire pour l'architecture de votre ordinateur - cela devrait être beaucoup plus rapide que tout code que vous pourriez raisonnablement écrire vous-même.
Ma petite contribution à ce problème.
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;
}
}
Arrgh, je ne peux pas obtenir le code pour apparaître correctement. Désolé, ça marche. Désolé encore, je ne pense pas avoir bien lu la question.
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++;
}
}
Si l'ordre des éléments n'a pas d'importance vous pouvez permuter entre les éléments foo [x] et foo [0], puis appelez foo.drop (1).
foo.drop(n)
supprime (n) les premiers éléments du tableau.
J'imagine que c'est le moyen le plus simple et le moins gourmand en ressources.
PS: indexOf
peut être implémenté de différentes manières, voici ma version.
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);
}
Copiera tous les éléments sauf celui d'indice 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) );
}
Dans un tableau de chaînes comme
Nom de chaîne = 'a b c d e a f b d e' // pourrait ressembler à Chaîne nom = 'aa bb c d e aa f bb d e'
Je construis la classe suivante
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()
obtenir ce résultat
a B c d e F
espérons que ce code aide quelqu'un Cordialement
Tableau initial
int[] array = {5,6,51,4,3,2};
si vous voulez supprimer 51 qui est l'index 2, utilisez la commande suivante
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
Cela dépend de ce que vous entendez par "enlever"? Un tableau est une construction de taille fixe - vous ne pouvez pas changer le nombre d'éléments qu'il contient. Vous pouvez donc a) créer un nouveau tableau plus court sans les éléments que vous ne voulez pas ou b) affecter les entrées que vous ne voulez pas à quelque chose qui indique leur statut «vide»; généralement null si vous ne travaillez pas avec des primitives.
Dans le premier cas, créez une liste à partir du tableau, supprimez les éléments et créez un nouveau tableau à partir de la liste. Si les performances sont importantes, effectuez une itération sur le tableau en affectant les éléments qui ne doivent pas être supprimés à une liste, puis créez un nouveau tableau à partir de la liste. Dans le second cas, il suffit de passer et d’attribuer la valeur null aux entrées du tableau.