157

I have an array of Foo objects. How do I remove the second element of the array?

I need something similar to RemoveAt() but for a regular array.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
leora
  • 188,729
  • 360
  • 878
  • 1,366
  • 1
    Use `System.Collections.ObjectModel.Collection`. – abatishchev Jan 19 '09 at 12:46
  • 2
    For my game I went with a "null at index" datastructure. Basically, the inner array(buffer) is of static size, and instead of removing the index and resizing the array, I just make the index null. When I need to add an item I just find the first non-null index and place it there. Works pretty well, but obviously not for everything. – Krythic Sep 17 '16 at 15:00

15 Answers15

234

If you don't want to use List:

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

You could try this extension method that I haven't actually tested:

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

And use it like:

Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);
Ram
  • 15,908
  • 4
  • 48
  • 41
Andrew Kennan
  • 13,947
  • 3
  • 24
  • 33
  • 10
    The first example given in this answer is much less efficient than the second. It requires two array copies and a shift of everything after index rather than one selective array copy. – Martin Brown Jan 19 '09 at 19:25
  • 2
    +1 of course, but we can also use list too OR List list = new List(GetFoos()); list.Remove(my_foo); list.RemoveAt(2); where GetFoos() will return the array of Foos !!!! – shahjapan Dec 18 '09 at 10:28
  • 2
    First line inside the method should say 'source.Length' instead of 'array.Length'. – Nelson Aug 06 '10 at 17:17
  • 1
    Also, keep in mind that any variable storing a reference to the original array will continue to contain the original data and that any reference equality comparison between the array in source and the output array will return a negative. – bkqc Aug 05 '16 at 18:42
  • 1
    @MartinBrown Actually, converting a list to\from and array is much slower than an array copy (which is able to copy the data at the max speed allowed by the CPU with just a few ASM instructions). Also, shifting a list is very fast because it is just a matter of swapping a few pointers and removing the node data (which is only 8 bytes [plus another 16 for the head\tail pointers] in this case). – krowe2 Jan 25 '17 at 23:12
  • @krowe2 you seem to be repeating what I said in different words with the word 'Actually' in front. Are you disagreeing? Note the question starts with an array not a list. In the second example there is in effect only one array copy as it copies it in two halves omitting the one item to be removed. In the first example there are two full copies and a shift. It copies the whole array to a list, then it shifts the items in the list then it copies the whole list back to an array. – Martin Brown Jan 26 '17 at 13:04
  • @MartinBrown You are right that the second is faster but converting an array to a list (or vice versa) is not an array copy operation. A list must be built. – krowe2 Jan 26 '17 at 16:03
  • 1
    @krowe2 a List is just an Array with a int Size value attached. When you call the List(IEnumerable) constructor it tries to cast the parameter to a ICollection and, if it succeeds, calls CopyTo on it to create its internal array. The CopyTo method on the Array class uses a fast array copy. So building a List from an Array is an array copy operation. You can check out the source here https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,d2ac2c19c9cf1d44,references – Martin Brown Jan 27 '17 at 11:17
80

The nature of arrays is that their length is immutable. You can't add or delete any of the array items.

You will have to create a new array that is one element shorter and copy the old items to the new array, excluding the element you want to delete.

So it is probably better to use a List instead of an array.

Jon B
  • 51,025
  • 31
  • 133
  • 161
Sebastian Dietz
  • 5,587
  • 1
  • 31
  • 39
72

I use this method for removing an element from an object array. In my situation, my arrays are small in length. So if you have large arrays you may need another 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;
}
daOnlyBG
  • 595
  • 4
  • 20
  • 49
EdHellyer
  • 721
  • 5
  • 3
  • 8
    Personally, I like this answer better than the accepted answer. It should be just as efficient, and it is much easier to read. I can look at it and know it is correct. I would have to test the other one to ensure those copies were written correctly. – oillio Mar 08 '11 at 18:45
  • 1
    It really is a shame this answer is so low, when it's by far better than the two above it. – Sepulchritude May 23 '12 at 15:51
  • Aaarhg, that is the answer I was looking for! This is the best method without Lists. – Jordi Huertas Feb 28 '19 at 19:00
58

LINQ one-line solution:

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

The 1 in that example is the index of the element to remove -- in this example, per the original question, the 2nd element (with 1 being the second element in C# zero-based array indexing).

A more complete example:

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

After running that snippet, the value of myArray will be { "a", "c", "d", "e" }.

Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
  • 2
    For areas requiring high-performance/frequent access, LINQ is not recommended. – Krythic Sep 17 '16 at 15:07
  • 3
    @Krythic That's a fair comment. Run thousands of times in a tight loop, this solution's performance isn't as as good as some of the other highly-voted solutions on this page: https://dotnetfiddle.net/z9Xkpn – Jon Schneider Sep 19 '16 at 15:26
12

This is a way to delete an array element, as of .Net 3.5, without copying to another array - using the same array instance with 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);
}
user7116
  • 63,008
  • 17
  • 141
  • 172
infografnet
  • 3,749
  • 1
  • 35
  • 35
  • 3
    "without copying to another array" - per the linked documentation, Array.Resize actually *does* allocate a new array behind the scenes, and copies the elements from the old array to the new one. Still, I like the conciseness of this solution. – Jon Schneider Sep 11 '14 at 14:48
  • Very Nice and clear if your sure it's a relatively small array. – Darren Jan 03 '15 at 06:14
  • 1
    Continuing @JonSchneider's comment, it is not "the same array instance". Which is why you need to use `ref` when you call the `Resize` method. The length of an array instance is fixed and immutable. – Jeppe Stig Nielsen Sep 17 '15 at 20:52
  • 2
    If the order of the elements is not important, instead of moving all elements downwards, you could swap the element at index with the last element and then resize: arr[index] = arr[arr.Length - 1]; Array.Resize(ref arr, arr.Length - 1); – Bartel Sep 24 '19 at 11:56
6

Here is an old version I have that works on version 1.0 of the .NET framework and does not need generic types.

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

This is used like this:

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]);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin Brown
  • 24,692
  • 14
  • 77
  • 122
5

Not exactly the way to go about this, but if the situation is trivial and you value your time, you can try this for nullable types.

Foos[index] = null

and later check for null entries in your logic..

nawfal
  • 70,104
  • 56
  • 326
  • 368
  • This is how I did it for my game. Go with nullable buffers for areas that are changed very frequently. – Krythic Sep 17 '16 at 15:05
3

Try below code:

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

or

myArray = myArray.Where(s => (s != "not_this")).ToArray();
Salman Zafar
  • 3,844
  • 5
  • 20
  • 43
Genci Ymeri
  • 104
  • 10
2

As usual, I'm late to the party...

I'd like to add another option to the nice solutions list already present. =)
I would see this as a good opportunity for Extensions.

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

So, we define some static class and in it, our Method.
After that, we can use our extended method willy-nilly. =)

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"
             */
        }
    }
}
Duncan
  • 1,530
  • 15
  • 20
1
    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;
    }
  • note that original question is about removing one element **by index**, while this solution removes elements **by value** – AntonK Mar 29 '23 at 10:16
1

Here's how I did it...

    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;
    }
Paul Mitchell
  • 3,241
  • 1
  • 19
  • 22
1

In a normal array you have to shuffle down all the array entries above 2 and then resize it using the Resize method. You might be better off using an ArrayList.

gkrogers
  • 8,126
  • 3
  • 29
  • 36
0

Here's a small collection of helper methods I produced based on some of the existing answers. It utilizes both extensions and static methods with reference parameters for maximum idealness:

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 wise, it is decent, but it could probably be improved. Remove relies on IndexOf and a new array is created for each element you wish to remove by calling RemoveAt.

IndexOf is the only extension method as it does not need to return the original array. New accepts multiple elements of some type to produce a new array of said type. All other methods must accept the original array as a reference so there is no need to assign the result afterward as that happens internally already.

I would've defined a Merge method for merging two arrays; however, that can already be accomplished with Add method by passing in an actual array versus multiple, individual elements. Therefore, Add may be used in the following two ways to join two sets of elements:

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

Or

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

I know this article is ten years old and therefore probably dead, but here's what I'd try doing:

Use the IEnumerable.Skip() method, found in System.Linq. It will skip the selected element from the array, and return another copy of the array that only contains everything except the selected object. Then just repeat that for every element you want removed and after that save it to a variable.

For example, if we have an array named "Sample" (of type int[]) with 5 numbers. We want to remove the 2nd one, so trying "Sample.Skip(2);" should return the same array except without the 2nd number.

commandertuna
  • 104
  • 1
  • 13
  • 1
    Doesn't this method just _bypasses a specified number of elements in a sequence and then returns the remaining elements_? In your example you will "skip" the first two elements of the generic list and not just the 2nd one! – xnr_z Nov 11 '19 at 11:23
-4

First step
You need to convert the array into a list, you could write an extension method like this

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

Second step
Write an extension method to convert back the list into an 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;
}

Last steps
Write your final method, but remember to remove the element at index before converting back to an array like the code show

public static string[] removeAt(string[] array, int index) {

    List<string> myList = array.ConnvertArrayToList();
    myList.RemoveAt(index);
    return myList.ConvertListToArray();
} 

examples codes could be find on my blog, keep tracking.

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Bamara Coulibaly
  • 729
  • 1
  • 8
  • 7
  • 14
    This is mildly insane considering the existence of `.ToArray()` and a `List` constructor which takes an existing sequence... – user7116 Jul 24 '13 at 18:19