Verwijder element van een gewone array

Ik heb een array met Foo-objecten. Hoe verwijder ik het tweede element van de array?

Ik heb iets nodig dat lijkt op RemoveAt()maar dan voor een gewone array.


Antwoord 1, autoriteit 100%

Als je Lijst niet wilt gebruiken:

var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();

Je zou deze extensiemethode kunnen proberen die ik niet echt heb getest:

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;
}

En gebruik het als:

Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);

Antwoord 2, autoriteit 34%

De aard van arrays is dat hun lengte onveranderlijk is. U kunt geen array-items toevoegen of verwijderen.

Je moet een nieuwe array maken die één element korter is en de oude items naar de nieuwe array kopiëren, met uitzondering van het element dat je wilt verwijderen.

Het is dus waarschijnlijk beter om een lijst te gebruiken in plaats van een array.


Antwoord 3, autoriteit 31%

Ik gebruik deze methode om een element uit een objectarray te verwijderen. In mijn situatie zijn mijn arrays klein van lengte. Dus als je grote arrays hebt, heb je misschien een andere oplossing nodig.

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;
}

Antwoord 4, autoriteit 23%

LINQ one-line oplossing:

myArray = myArray.Where((source, index) => index != 1).ToArray();

De 1in dat voorbeeld is de index van het te verwijderen element — in dit voorbeeld, volgens de oorspronkelijke vraag, het 2e element (met 1als tweede element in C# op nul gebaseerde array-indexering).

Een vollediger voorbeeld:

string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();

Na het uitvoeren van dat fragment is de waarde van myArray{ "a", "c", "d", "e" }.


Antwoord 5, autoriteit 5%

Dit is een manier om een array-element te verwijderen, vanaf .Net 3.5, zonder te kopiëren naar een andere array – met dezelfde array-instantie met 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);
}

Antwoord 6, autoriteit 3%

Hier is een oude versie die ik heb die werkt op versie 1.0 van het .NETframework en heeft geen generieke typen nodig.

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;
}

Dit wordt als volgt gebruikt:

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]);
    }
}

Antwoord 7

Niet echt de juiste manier om dit aan te pakken, maar als de situatie triviaal is en je waarde hecht aan je tijd, kun je dit proberen voor nullable-typen.

Foos[index] = null

en later controleren op null-vermeldingen in uw logica..


Antwoord 8

Zoals gewoonlijk ben ik te laat op het feest…

Ik wil graag nog een optie toevoegen aan de lijst met leuke oplossingen die al aanwezig is. =)
Ik zou dit zien als een goede kans voor extensies.

Referentie:
http://msdn.microsoft.com/en-us/library/bb311042.aspx

Dus we definiëren een statische klasse en daarin onze methode.
Daarna kunnen we willekeurig onze uitgebreide methode gebruiken. =)

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"
             */
        }
    }
}

Antwoord 9

Probeer onderstaande code:

myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();

of

myArray = myArray.Where(s => (s != "not_this")).ToArray();

Antwoord 10

Dit is hoe ik het deed…

   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;
    }

Antwoord 11

In een normale array moet je alle array-items boven de 2 in willekeurige volgorde weergeven en vervolgens de grootte ervan wijzigen met behulp van de methode Resize. Misschien ben je beter af met een ArrayList.


Antwoord 12

   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;
    }

Antwoord 13

Hier is een kleine verzameling helpermethoden die ik heb geproduceerd op basis van enkele van de bestaande antwoorden. Het maakt gebruik van beide extensies als statische methoden met referentieparameters voor maximale idealiteit:

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;
    }
}

Wat de prestaties betreft, is het redelijk, maar het kan waarschijnlijk worden verbeterd. Removeis afhankelijk van IndexOfen er wordt een nieuwe array gemaakt voor elk element dat u wilt verwijderen door RemoveAtaan te roepen.

IndexOfis de enige extensiemethode omdat het de originele array niet hoeft terug te geven. Newaccepteert meerdere elementen van een bepaald type om een nieuwe array van dat type te produceren. Alle andere methoden moeten de originele array als referentie accepteren, dus het is niet nodig om het resultaat achteraf toe te wijzen, omdat dat intern al gebeurt.

Ik zou een Mergemethode hebben gedefinieerd om twee arrays samen te voegen; dat kan echter al worden bereikt met de methode Adddoor een daadwerkelijke array door te geven in plaats van meerdere, afzonderlijke elementen. Daarom kan Addop de volgende twee manieren worden gebruikt om twee sets elementen samen te voegen:

Arr.Add<string>(ref myArray, "A", "B", "C");

Of

Arr.Add<string>(ref myArray, anotherArray);

Antwoord 14

Ik weet dat dit artikel tien jaar oud is en daarom waarschijnlijk dood, maar ik zou het volgende proberen:

Gebruik de IEnumerable.Skip() methode, gevonden in System.Linq. Het zal het geselecteerde element uit de array overslaan en een andere kopie van de array retourneren die alleen alles bevat behalve het geselecteerde object. Herhaal dat dan gewoon voor elk element dat u wilt verwijderen en sla het daarna op in een variabele.

Bijvoorbeeld als we een array hebben met de naam “Sample” (van het type int[]) met 5 getallen. We willen de 2e verwijderen, dus probeer “Sample.Skip(2);” zou dezelfde array moeten retourneren, behalve zonder het 2e getal.


Antwoord 15

Eerste stap
Je moet de array converteren naar een lijst, je zou een extensiemethode als deze kunnen schrijven

// 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;
} 

Tweede stap
Schrijf een extensiemethode om de lijst terug te converteren naar een 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;
}

Laatste stappen
Schrijf je laatste methode, maar vergeet niet om het element bij index te verwijderen voordat je het terug converteert naar een array zoals de codeshow

public static string[] removeAt(string[] array, int index) {
    List<string> myList = array.ConnvertArrayToList();
    myList.RemoveAt(index);
    return myList.ConvertListToArray();
} 

voorbeeldcodes zijn te vinden op mijn blog, blijf volgen.

Other episodes