J'ai un tableau d'objets Foo. Comment supprimer le deuxième élément du tableau?
J'ai besoin de quelque chose de similaire à RemoveAt()
mais pour un tableau régulier.
J'ai un tableau d'objets Foo. Comment supprimer le deuxième élément du tableau?
J'ai besoin de quelque chose de similaire à RemoveAt()
mais pour un tableau régulier.
Réponses:
Si vous ne souhaitez pas utiliser List:
var foos = new List<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:
public static 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;
}
Et utilisez-le comme:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
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.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
utilisant la Enumerable.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.
private int[] RemoveIndices(int[] IndicesArray, int RemoveAt)
{
int[] newIndicesArray = new int[IndicesArray.Length - 1];
int i = 0;
int j = 0;
while (i < IndicesArray.Length)
{
if (i != RemoveAt)
{
newIndicesArray[j] = IndicesArray[i];
j++;
}
i++;
}
return newIndicesArray;
}
Solution LINQ en une ligne:
myArray = myArray.Where((source, index) => index != 1).ToArray();
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:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Après avoir exécuté cet extrait de code, la valeur de myArray
sera { "a", "c", "d", "e" }
.
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>
:
public static void RemoveAt<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 one
Array.Resize(ref arr, arr.Length - 1);
}
ref
lorsque vous appelez la Resize
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.
public static Array RemoveAt(Array source, int index)
{
if (source == null)
throw new ArgumentNullException("source");
if (0 > index || index >= source.Length)
throw new ArgumentOutOfRangeException("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:
class Program
{
static void Main(string[] args)
{
string[] x = new string[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.
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é. =)
using System;
namespace FunctionTesting {
// The class doesn't matter, as long as it's static
public static class SomeRandomClassWhoseNameDoesntMatter {
// Here's the actual method that extends arrays
public static T[] RemoveAt<T>( this T[] oArray, int idx ) {
T[] nArray = new T[oArray.Length - 1];
for( int i = 0; i < nArray.Length; ++i ) {
nArray[i] = ( i < idx ) ? oArray[i] : oArray[i + 1];
}
return nArray;
}
}
// Sample usage...
class Program {
static void Main( string[] args ) {
string[] myStrArray = { "Zero", "One", "Two", "Three" };
Console.WriteLine( String.Join( " ", myStrArray ) );
myStrArray = myStrArray.RemoveAt( 2 );
Console.WriteLine( String.Join( " ", myStrArray ) );
/* Output
* "Zero One Two Three"
* "Zero One Three"
*/
int[] myIntArray = { 0, 1, 2, 3 };
Console.WriteLine( String.Join( " ", myIntArray ) );
myIntArray = myIntArray.RemoveAt( 2 );
Console.WriteLine( String.Join( " ", myIntArray ) );
/* Output
* "0 1 2 3"
* "0 1 3"
*/
}
}
}
Essayez le code ci-dessous:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
ou
myArray = myArray.Where(s => (s != "not_this")).ToArray();
Voici comment je l'ai fait ...
public static ElementDefinitionImpl[] RemoveElementDefAt(
ElementDefinition[] oldList,
int removeIndex
)
{
ElementDefinitionImpl[] newElementDefList = new ElementDefinitionImpl[ oldList.Length - 1 ];
int offset = 0;
for ( int index = 0; index < oldList.Length; index++ )
{
ElementDefinitionImpl elementDef = oldList[ index ] as ElementDefinitionImpl;
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;
}
private int[] removeFromArray(int[] array, int id)
{
int difference = 0, currentValue=0;
//get new Array length
for (int i=0; i<array.Length; i++)
{
if (array[i]==id)
{
difference += 1;
}
}
//create new array
int[] newArray = new int[array.Length-difference];
for (int i = 0; i < array.Length; i++ )
{
if (array[i] != id)
{
newArray[currentValue] = array[i];
currentValue += 1;
}
}
return newArray;
}
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:
public static class Arr
{
public static int IndexOf<TElement>(this TElement[] Source, TElement Element)
{
for (var i = 0; i < Source.Length; i++)
{
if (Source[i].Equals(Element))
return i;
}
return -1;
}
public static TElement[] Add<TElement>(ref TElement[] Source, params TElement[] Elements)
{
var OldLength = Source.Length;
Array.Resize(ref Source, OldLength + Elements.Length);
for (int j = 0, Count = Elements.Length; j < Count; j++)
Source[OldLength + j] = Elements[j];
return Source;
}
public static TElement[] New<TElement>(params TElement[] Elements)
{
return Elements ?? new TElement[0];
}
public static void Remove<TElement>(ref TElement[] Source, params TElement[] Elements)
{
foreach (var i in Elements)
RemoveAt(ref Source, Source.IndexOf(i));
}
public static void RemoveAt<TElement>(ref TElement[] Source, int Index)
{
var Result = new TElement[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é. Remove
s'appuie sur IndexOf
et un nouveau tableau est créé pour chaque élément que vous souhaitez supprimer en appelant RemoveAt
.
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 la Add
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:
Arr.Add<string>(ref myArray, "A", "B", "C");
Ou
Arr.Add<string>(ref myArray, anotherArray);
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.
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 string
public static List<string> ConnvertArrayToList(this string [] array) {
// DECLARE a list of string and add all element of the array into it
List<string> myList = new List<string>();
foreach( string s in array){
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
public static string[] ConvertListToArray(this List<string> list) {
string[] array = new string[list.Capacity];
array = list.Select(i => i.ToString()).ToArray();
return array;
}
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
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
des exemples de codes pourraient être trouvés sur mon blog , continuez à suivre.
.ToArray()
et d'un List<T>
constructeur qui prend une séquence existante ...
System.Collections.ObjectModel.Collection<Foo>
.