J'ai un tableau d'objets Foo. Comment puis-je supprimer le deuxième élément du tableau?
J'ai besoin de quelque chose de similaire à RemoveAt()
mais pour un tableau régulier.
Si vous ne voulez 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 encore 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 ajouter ou 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 à supprimer.
Il est donc probablement préférable d’utiliser une liste plutôt qu’un tableau.
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 grands tableaux, 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 linéaire LINQ:
myArray = myArray.Where((source, index) => index != 1).ToArray();
1
dans cet exemple correspond à l'index de l'élément à supprimer - dans cet exemple, pour la question d'origine, le deuxième élément (1
étant le deuxième élément de l'indexation de tableaux basée sur 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, la valeur de myArray
sera { "a", "c", "d", "e" }
.
C'est une façon 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);
}
Voici une ancienne version que j'ai qui fonctionne sur la version 1.0 du .NET framework et 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 vraiment la façon de procéder, mais si la situation est triviale et que vous accordez de la valeur à votre temps, vous pouvez l’essayer pour les types nullables.
Foos[index] = null
et plus tard, vérifiez les entrées nulles dans votre logique.
Comme d'habitude, je suis en retard à la fête ...
J'aimerais ajouter une autre option à la liste des solutions de Nice 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
Nous définissons donc une classe statique et 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"
*/
}
}
}
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 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;
}
Dans un tableau normal, vous devez mélanger toutes les entrées de tableau supérieures à 2, puis le redimensionner à l'aide de la méthode Resize. Vous feriez peut-être mieux d'utiliser une liste de tableaux.
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 va ignorer l'élément sélectionné du tableau et renvoyer une autre copie du tableau qui ne contient que tout sauf l'objet sélectionné. Ensuite, répétez-le pour chaque élément à supprimer, puis enregistrez-le dans une variable.
Par exemple, si nous avons un tableau nommé "Sample" (de type int []) avec 5 nombres. Nous voulons supprimer le deuxième, essayez donc "Sample.Skip (2);" devrait renvoyer le même tableau sauf sans le 2e nombre.
Voici une petite collection de méthodes d’aide que j’ai produite à partir 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 un maximum d’idéalité:
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;
}
}
Performance sage, il est décent, mais il 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 il n'est pas nécessaire de renvoyer le tableau d'origine. New
accepte plusieurs éléments d'un type quelconque pour produire un nouveau tableau de ce type. Toutes les autres méthodes doivent accepter le tableau d'origine en tant que référence, il n'est donc pas nécessaire d'affecter le résultat ultérieurement, car cela se produit déjà en interne.
J'aurais défini une méthode Merge
pour fusionner deux tableaux; Cependant, cela peut déjà être accompli avec la méthode Add
en transmettant un tableau réel au lieu de plusieurs éléments individuels. Par conséquent, Add
peut être utilisé de deux manières pour joindre deux ensembles d’éléments:
Arr.Add<string>(ref myArray, "A", "B", "C");
Ou
Arr.Add<string>(ref myArray, anotherArray);