Ho una serie di oggetti Foo. Come rimuovo il secondo elemento dell'array?
Ho bisogno di qualcosa di simile a RemoveAt()
ma per un array normale.
Ho una serie di oggetti Foo. Come rimuovo il secondo elemento dell'array?
Ho bisogno di qualcosa di simile a RemoveAt()
ma per un array normale.
Risposte:
Se non si desidera utilizzare Elenco:
var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();
Potresti provare questo metodo di estensione che non ho ancora testato:
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;
}
E usalo come:
Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
La natura degli array è che la loro lunghezza è immutabile. Non è possibile aggiungere o eliminare nessuno degli elementi dell'array.
Dovrai creare un nuovo array più corto di un elemento e copiare i vecchi elementi nel nuovo array, escludendo l'elemento che desideri eliminare.
Quindi è probabilmente meglio usare un elenco anziché un array.
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
usando il Enumerable.ToList()
metodo dallo System.Linq
spazio dei nomi.
Uso questo metodo per rimuovere un elemento da un array di oggetti. Nella mia situazione, i miei array sono di lunghezza ridotta. Quindi, se si dispone di array di grandi dimensioni, potrebbe essere necessaria un'altra soluzione.
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;
}
Soluzione LINQ a una riga:
myArray = myArray.Where((source, index) => index != 1).ToArray();
In 1
questo esempio è l'indice dell'elemento da rimuovere - in questo esempio, per la domanda originale, il 2 ° elemento (con 1
il secondo elemento nell'indicizzazione di array basato su zero C #).
Un esempio più completo:
string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();
Dopo aver eseguito lo snippet, il valore di myArray
sarà { "a", "c", "d", "e" }
.
Questo è un modo per eliminare un elemento dell'array, a partire da .Net 3.5, senza copiarlo in un altro array - usando la stessa istanza dell'array con 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
quando si chiama il Resize
metodo. La lunghezza di un'istanza di array è fissa e immutabile.
Ecco una vecchia versione che ho che funziona sulla versione 1.0 del framework .NET e non necessita di tipi generici.
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;
}
Questo è usato in questo modo:
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]);
}
}
Non è esattamente il modo di procedere, ma se la situazione è banale e apprezzi il tuo tempo, puoi provare questo per tipi nulli.
Foos[index] = null
e successivamente verifica la presenza di voci nulle nella tua logica.
Come al solito, sono in ritardo alla festa ...
Vorrei aggiungere un'altra opzione al simpatico elenco di soluzioni già presente. =)
Vorrei che questa fosse una buona opportunità per le estensioni.
Riferimento:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Quindi, definiamo una classe statica e in essa il nostro Metodo.
Dopo ciò, possiamo usare il nostro metodo esteso volenti o nolenti. =)
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"
*/
}
}
}
Prova sotto il codice:
myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();
o
myArray = myArray.Where(s => (s != "not_this")).ToArray();
Ecco come l'ho fatto ...
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;
}
Ecco una piccola raccolta di metodi di supporto che ho prodotto sulla base di alcune delle risposte esistenti. Utilizza estensioni e metodi statici con parametri di riferimento per la massima idealità:
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;
}
}
Per quanto riguarda le prestazioni, è decente, ma probabilmente potrebbe essere migliorato. Remove
si affida IndexOf
e viene creato un nuovo array per ogni elemento che si desidera rimuovere chiamando RemoveAt
.
IndexOf
è l'unico metodo di estensione in quanto non è necessario restituire l'array originale. New
accetta più elementi di un certo tipo per produrre un nuovo array di detto tipo. Tutti gli altri metodi devono accettare l'array originale come riferimento, quindi non è necessario assegnare il risultato in seguito poiché ciò già avviene internamente.
Avrei definito un Merge
metodo per unire due matrici; tuttavia, ciò può essere già realizzato con il Add
metodo passando un array effettivo rispetto a più singoli elementi. Pertanto, Add
possono essere utilizzati nei seguenti due modi per unire due serie di elementi:
Arr.Add<string>(ref myArray, "A", "B", "C");
O
Arr.Add<string>(ref myArray, anotherArray);
So che questo articolo ha dieci anni e quindi probabilmente è morto, ma ecco cosa proverei a fare:
Utilizzare il metodo IEnumerable.Skip (), presente in System.Linq . Salterà l'elemento selezionato dall'array e restituirà un'altra copia dell'array che contiene solo tutto tranne l'oggetto selezionato. Quindi ripeti l'operazione per ogni elemento che desideri rimuovere e successivamente salvalo in una variabile.
Ad esempio, se abbiamo una matrice denominata "Esempio" (di tipo int []) con 5 numeri. Vogliamo rimuovere il secondo, quindi provando "Sample.Skip (2);" dovrebbe restituire lo stesso array ad eccezione del 2o numero.
Primo passo
È necessario convertire l'array in un elenco, è possibile scrivere un metodo di estensione come questo
// 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;
}
Secondo passaggio
Scrivere un metodo di estensione per riconvertire l'elenco in un array
// 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;
}
Ultimi passi
Scrivi il tuo metodo finale, ma ricorda di rimuovere l'elemento all'indice prima di riconvertirlo in un array come il code show
public static string[] removeAt(string[] array, int index) {
List<string> myList = array.ConnvertArrayToList();
myList.RemoveAt(index);
return myList.ConvertListToArray();
}
esempi codici potrebbero essere trovati sul mio blog , continua a tenere traccia.
.ToArray()
un List<T>
costruttore che prende una sequenza esistente ...
System.Collections.ObjectModel.Collection<Foo>
.