Pour mon jeu, je suis allé avec une structure de données "null at index". Fondamentalement, le tableau interne (tampon) est de taille statique, et au lieu de supprimer l'index et de redimensionner le tableau, je rends simplement l'index nul. Quand j'ai besoin d'ajouter un élément, je trouve juste le premier index non nul et je le place là. Fonctionne plutôt bien, mais évidemment pas pour tout.
Krythic
Réponses:
202
Si vous ne souhaitez pas utiliser List:
var foos =newList<Foo>(array);
foos.RemoveAt(index);return foos.ToArray();
Vous pouvez essayer cette méthode d'extension que je n'ai pas réellement testée:
publicstatic T[]RemoveAt<T>(this T[] source,int index){
T[] dest =new T[source.Length-1];if( index >0)Array.Copy(source,0, dest,0, index);if( index < source.Length-1)Array.Copy(source, index +1, dest, index, source.Length- index -1);return dest;}
Le premier exemple donné dans cette réponse est beaucoup moins efficace que le second. Il nécessite deux copies de tableau et un décalage de tout après l'index plutôt qu'une copie de tableau sélective.
Martin Brown
2
+1 bien sûr, mais nous pouvons aussi utiliser list OU List <Foo> list = new List <Foll> (GetFoos ()); list.Remove (mon_chot); list.RemoveAt (2); où GetFoos () renverra le tableau de Foos !!!!
shahjapan
2
La première ligne de la méthode doit indiquer «source.Length» au lieu de «array.Length».
Nelson
1
Gardez également à l'esprit que toute variable stockant une référence au tableau d'origine continuera à contenir les données d'origine et que toute comparaison d'égalité de référence entre le tableau de la source et le tableau de sortie renverra un négatif.
bkqc
1
@MartinBrown En fait, la conversion d'une liste en \ from et array est beaucoup plus lente qu'une copie de tableau (qui est capable de copier les données à la vitesse maximale autorisée par le CPU avec seulement quelques instructions ASM). De plus, le décalage d'une liste est très rapide car il s'agit juste d'échanger quelques pointeurs et de supprimer les données du nœud (qui ne font que 8 octets [plus 16 autres pour les pointeurs head \ tail] dans ce cas).
krowe2
66
La nature des tableaux est que leur longueur est immuable. Vous ne pouvez ni ajouter ni supprimer aucun des éléments du tableau.
Vous devrez créer un nouveau tableau d'un élément plus court et copier les anciens éléments dans le nouveau tableau, à l'exclusion de l'élément que vous souhaitez supprimer.
Il est donc probablement préférable d'utiliser une liste au lieu d'un tableau.
Convertir le tableau en listeList<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
Immortal Blue
1
@ImmortalBlue ou simplement en var myList = myArray.ToList();utilisant la Enumerable.ToList()méthode de l' System.Linqespace de noms.
Dyndrilliac
58
J'utilise cette méthode pour supprimer un élément d'un tableau d'objets. Dans ma situation, mes tableaux sont de petite longueur. Donc, si vous avez de grandes baies, vous aurez peut-être besoin d'une autre solution.
Personnellement, j'aime mieux cette réponse que la réponse acceptée. Il doit être tout aussi efficace et beaucoup plus facile à lire. Je peux le regarder et je sais qu'il est correct. Je devrais tester l'autre pour m'assurer que ces copies étaient écrites correctement.
oillio
1
C'est vraiment dommage que cette réponse soit si basse, alors qu'elle est de loin meilleure que les deux ci-dessus.
Sepulchritude
Aaarhg, c'est la réponse que je cherchais! C'est la meilleure méthode sans listes.
Jordi Huertas
47
Solution LINQ en une ligne:
myArray = myArray.Where((source, index)=> index !=1).ToArray();
Le 1dans cet exemple est l'index de l'élément à supprimer - dans cet exemple, par la question d'origine, le 2ème élément (avec1 étant le second élément dans l'indexation de tableau de base zéro C #).
Pour les zones nécessitant un accès fréquent / hautes performances, LINQ n'est pas recommandé.
Krythic le
3
@Krythic C'est un commentaire juste. Exécutée des milliers de fois dans une boucle serrée, les performances de cette solution ne sont pas aussi bonnes que certaines des autres solutions les plus appréciées de cette page: dotnetfiddle.net/z9Xkpn
Jon Schneider
9
C'est un moyen de supprimer un élément de tableau, à partir de .Net 3.5, sans copier dans un autre tableau - en utilisant la même instance de tableau avec Array.Resize<T>:
publicstaticvoidRemoveAt<T>(ref T[] arr,int index){for(int a = index; a < arr.Length-1; a++){// moving elements downwards, to fill the gap at [index]
arr[a]= arr[a +1];}// finally, let's decrement Array's size by oneArray.Resize(ref arr, arr.Length-1);}
"sans copier dans un autre tableau" - selon la documentation liée, Array.Resize alloue en fait un nouveau tableau dans les coulisses et copie les éléments de l'ancien tableau vers le nouveau. Pourtant, j'aime la concision de cette solution.
Jon Schneider du
Très agréable et clair si vous êtes sûr que c'est un tableau relativement petit.
Darren
1
Poursuivant le commentaire de @ JonSchneider, ce n'est pas "la même instance de tableau". C'est pourquoi vous devez utiliser reflorsque vous appelez la Resizeméthode. La longueur d'une instance de tableau est fixe et immuable.
Jeppe Stig Nielsen
2
Si l'ordre des éléments n'est pas important, au lieu de déplacer tous les éléments vers le bas, vous pouvez permuter l'élément à l'index avec le dernier élément, puis redimensionner: arr [index] = arr [arr.Length - 1]; Array.Resize (ref arr, arr.Length - 1);
Bartel
5
Voici une ancienne version que j'ai qui fonctionne sur la version 1.0 du framework .NET et qui n'a pas besoin de types génériques.
publicstaticArrayRemoveAt(Array source,int index){if(source ==null)thrownewArgumentNullException("source");if(0> index || index >= source.Length)thrownewArgumentOutOfRangeException("index", index,"index is outside the bounds of source array");Array dest =Array.CreateInstance(source.GetType().GetElementType(), source.Length-1);Array.Copy(source,0, dest,0, index);Array.Copy(source, index +1, dest, index, source.Length- index -1);return dest;}
Ceci est utilisé comme ceci:
classProgram{staticvoidMain(string[] args){string[] x =newstring[20];for(int i =0; i < x.Length; i++)
x[i]=(i+1).ToString();string[] y =(string[])MyArrayFunctions.RemoveAt(x,3);for(int i =0; i < y.Length; i++)Console.WriteLine(y[i]);}}
Ce n'est pas exactement la façon de procéder, mais si la situation est triviale et que vous appréciez votre temps, vous pouvez essayer ceci pour les types Nullable.
Foos[index]=null
et vérifiez plus tard les entrées nulles dans votre logique.
publicstaticElementDefinitionImpl[]RemoveElementDefAt(ElementDefinition[] oldList,int removeIndex
){ElementDefinitionImpl[] newElementDefList =newElementDefinitionImpl[ oldList.Length-1];int offset =0;for(int index =0; index < oldList.Length; index++){ElementDefinitionImpl elementDef = oldList[ index ]asElementDefinitionImpl;if( index == removeIndex ){// This is the one we want to remove, so we won't copy it. But // every subsequent elementDef will by shifted down by one.
offset =-1;}else{
newElementDefList[ index + offset ]= elementDef;}}return newElementDefList;}
Dans un tableau normal, vous devez mélanger toutes les entrées du tableau au-dessus de 2, puis le redimensionner à l'aide de la méthode Resize. Vous feriez peut-être mieux d'utiliser une ArrayList.
Voici une petite collection de méthodes d'aide que j'ai produites sur la base de certaines des réponses existantes. Il utilise à la fois des extensions et des méthodes statiques avec des paramètres de référence pour une idéalité maximale:
publicstaticclassArr{publicstaticintIndexOf<TElement>(thisTElement[]Source,TElementElement){for(var i =0; i <Source.Length; i++){if(Source[i].Equals(Element))return i;}return-1;}publicstaticTElement[]Add<TElement>(refTElement[]Source,paramsTElement[]Elements){varOldLength=Source.Length;Array.Resize(refSource,OldLength+Elements.Length);for(int j =0,Count=Elements.Length; j <Count; j++)Source[OldLength+ j]=Elements[j];returnSource;}publicstaticTElement[]New<TElement>(paramsTElement[]Elements){returnElements??newTElement[0];}publicstaticvoidRemove<TElement>(refTElement[]Source,paramsTElement[]Elements){foreach(var i inElements)RemoveAt(refSource,Source.IndexOf(i));}publicstaticvoidRemoveAt<TElement>(refTElement[]Source,intIndex){varResult=newTElement[Source.Length-1];if(Index>0)Array.Copy(Source,0,Result,0,Index);if(Index<Source.Length-1)Array.Copy(Source,Index+1,Result,Index,Source.Length-Index-1);Source=Result;}}
En termes de performances, c'est décent, mais cela pourrait probablement être amélioré. Removes'appuie sur IndexOfet un nouveau tableau est créé pour chaque élément que vous souhaitez supprimer en appelant RemoveAt.
IndexOfest la seule méthode d'extension car elle n'a pas besoin de renvoyer le tableau d'origine. Newaccepte plusieurs éléments d'un certain type pour produire un nouveau tableau dudit type. Toutes les autres méthodes doivent accepter le tableau d'origine comme référence, il n'est donc pas nécessaire d'affecter le résultat par la suite, car cela se produit déjà en interne.
J'aurais défini une Mergeméthode pour fusionner deux tableaux; cependant, cela peut déjà être accompli avec la Addméthode en passant un tableau réel par rapport à plusieurs éléments individuels. Par conséquent, Addpeut être utilisé des deux manières suivantes pour joindre deux ensembles d'éléments:
Je sais que cet article a dix ans et donc probablement mort, mais voici ce que j'essaierais de faire:
Utilisez la méthode IEnumerable.Skip (), trouvée dans System.Linq . Il sautera l'élément sélectionné du tableau et retournera une autre copie du tableau qui ne contient que tout sauf l'objet sélectionné. Ensuite, répétez simplement cela pour chaque élément que vous souhaitez supprimer et enregistrez-le ensuite dans une variable.
Par exemple, si nous avons un tableau nommé "Sample" (de type int []) avec 5 nombres. Nous voulons supprimer le 2ème, donc en essayant "Sample.Skip (2);" doit renvoyer le même tableau, sauf sans le deuxième numéro.
Cette méthode ne contourne- t-elle pas simplement un nombre spécifié d'éléments dans une séquence, puis retourne les éléments restants ? Dans votre exemple, vous «sauterez» les deux premiers éléments de la liste générique et pas seulement le 2ème!
xnr_z
-4
Première étape
Vous devez convertir le tableau en une liste, vous pouvez écrire une méthode d'extension comme celle-ci
// Convert An array of string to a list of stringpublicstaticList<string>ConnvertArrayToList(thisstring[]array){// DECLARE a list of string and add all element of the array into itList<string> myList =newList<string>();foreach(string s inarray){
myList.Add(s);}return myList;}
Deuxième étape
Écrivez une méthode d'extension pour reconvertir la liste en un tableau
// convert a list of string to an array publicstaticstring[]ConvertListToArray(thisList<string>list){string[]array=newstring[list.Capacity];array=list.Select(i => i.ToString()).ToArray();returnarray;}
Dernières étapes
Écrivez votre méthode finale, mais n'oubliez pas de supprimer l'élément à l'index avant de reconvertir en un tableau comme le code montre
System.Collections.ObjectModel.Collection<Foo>
.Réponses:
Si vous ne souhaitez pas utiliser List:
Vous pouvez essayer cette méthode d'extension que je n'ai pas réellement testée:
Et utilisez-le comme:
la source
La nature des tableaux est que leur longueur est immuable. Vous ne pouvez ni ajouter ni supprimer aucun des éléments du tableau.
Vous devrez créer un nouveau tableau d'un élément plus court et copier les anciens éléments dans le nouveau tableau, à l'exclusion de l'élément que vous souhaitez supprimer.
Il est donc probablement préférable d'utiliser une liste au lieu d'un tableau.
la source
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
utilisant laEnumerable.ToList()
méthode de l'System.Linq
espace de noms.J'utilise cette méthode pour supprimer un élément d'un tableau d'objets. Dans ma situation, mes tableaux sont de petite longueur. Donc, si vous avez de grandes baies, vous aurez peut-être besoin d'une autre solution.
la source
Solution LINQ en une ligne:
Le
1
dans cet exemple est l'index de l'élément à supprimer - dans cet exemple, par la question d'origine, le 2ème élément (avec1
étant le second élément dans l'indexation de tableau de base zéro C #).Un exemple plus complet:
Après avoir exécuté cet extrait de code, la valeur de
myArray
sera{ "a", "c", "d", "e" }
.la source
C'est un moyen de supprimer un élément de tableau, à partir de .Net 3.5, sans copier dans un autre tableau - en utilisant la même instance de tableau avec
Array.Resize<T>
:la source
ref
lorsque vous appelez laResize
méthode. La longueur d'une instance de tableau est fixe et immuable.Voici une ancienne version que j'ai qui fonctionne sur la version 1.0 du framework .NET et qui n'a pas besoin de types génériques.
Ceci est utilisé comme ceci:
la source
Ce n'est pas exactement la façon de procéder, mais si la situation est triviale et que vous appréciez votre temps, vous pouvez essayer ceci pour les types Nullable.
et vérifiez plus tard les entrées nulles dans votre logique.
la source
Comme d'habitude, je suis en retard à la fête ...
J'aimerais ajouter une autre option à la belle liste de solutions déjà présente. =)
Je verrais cela comme une bonne opportunité pour les extensions.
Référence: http://msdn.microsoft.com/en-us/library/bb311042.aspx
Donc, nous définissons une classe statique et en elle, notre méthode.
Après cela, nous pouvons utiliser notre méthode étendue bon gré mal gré. =)
la source
Essayez le code ci-dessous:
ou
la source
Voici comment je l'ai fait ...
la source
Dans un tableau normal, vous devez mélanger toutes les entrées du tableau au-dessus de 2, puis le redimensionner à l'aide de la méthode Resize. Vous feriez peut-être mieux d'utiliser une ArrayList.
la source
la source
Voici une petite collection de méthodes d'aide que j'ai produites sur la base de certaines des réponses existantes. Il utilise à la fois des extensions et des méthodes statiques avec des paramètres de référence pour une idéalité maximale:
En termes de performances, c'est décent, mais cela pourrait probablement être amélioré.
Remove
s'appuie surIndexOf
et un nouveau tableau est créé pour chaque élément que vous souhaitez supprimer en appelantRemoveAt
.IndexOf
est la seule méthode d'extension car elle n'a pas besoin de renvoyer le tableau d'origine.New
accepte plusieurs éléments d'un certain type pour produire un nouveau tableau dudit type. Toutes les autres méthodes doivent accepter le tableau d'origine comme référence, il n'est donc pas nécessaire d'affecter le résultat par la suite, car cela se produit déjà en interne.J'aurais défini une
Merge
méthode pour fusionner deux tableaux; cependant, cela peut déjà être accompli avec laAdd
méthode en passant un tableau réel par rapport à plusieurs éléments individuels. Par conséquent,Add
peut être utilisé des deux manières suivantes pour joindre deux ensembles d'éléments:Ou
la source
Je sais que cet article a dix ans et donc probablement mort, mais voici ce que j'essaierais de faire:
Utilisez la méthode IEnumerable.Skip (), trouvée dans System.Linq . Il sautera l'élément sélectionné du tableau et retournera une autre copie du tableau qui ne contient que tout sauf l'objet sélectionné. Ensuite, répétez simplement cela pour chaque élément que vous souhaitez supprimer et enregistrez-le ensuite dans une variable.
Par exemple, si nous avons un tableau nommé "Sample" (de type int []) avec 5 nombres. Nous voulons supprimer le 2ème, donc en essayant "Sample.Skip (2);" doit renvoyer le même tableau, sauf sans le deuxième numéro.
la source
Première étape
Vous devez convertir le tableau en une liste, vous pouvez écrire une méthode d'extension comme celle-ci
Deuxième étape
Écrivez une méthode d'extension pour reconvertir la liste en un tableau
Dernières étapes
Écrivez votre méthode finale, mais n'oubliez pas de supprimer l'élément à l'index avant de reconvertir en un tableau comme le code montre
des exemples de codes pourraient être trouvés sur mon blog , continuez à suivre.
la source
.ToArray()
et d'unList<T>
constructeur qui prend une séquence existante ...