In this article, we will explore several different ways to delete elements from an array in C# based on their value and compare their performance to help you choose the best option for your specific use case.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin!

Arrays in .NET

Arrays are a fundamental data structure in .NET, allowing developers to easily store and manipulate collections of data. However, deleting elements from an array can be a challenging task, as the size of the array is fixed once we initialize it.

To overcome this, we will demonstrate various techniques to remove elements from an array, each with its advantages and disadvantages.

Methods to Delete Array Elements

Array type does not have a built-in method for this task and we often resort to alternative techniques such as converting the Array to a List or utilizing LINQ to remove specific elements from the Array. These methods provide greater flexibility and ease when it comes to removing unwanted elements from the Array.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

The solutions are built with integer arrays for demonstration purposes, but we can apply them to any data type.

We’ll start by setting up a simple example to test against our methods:

var array = new int[]{ 3, 4, 5, 3, 5, 7 };
var elementToDelete = 3;

Here, we construct an array of integers and we assign to the elementToDelete variable the value we want to remove from our collection.

Use Array.Copy() To Delete an Element From an Array

First, we will manually remove it with the ArrayCopy() extension method:

public int[] DeleteWithArrayCopy(int[] inputArray, int elementToRemove) 
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);

    if (indexToRemove < 0) 
    {
        return inputArray;
    }

    var tempArray = new int[inputArray.Length - 1];

    Array.Copy(inputArray, 0, tempArray, 0, indexToRemove);
    Array.Copy(inputArray, indexToRemove + 1, tempArray, indexToRemove, inputArray.Length - indexToRemove - 1);

    return tempArray;
}

The DeleteWithArrayCopy() method takes as arguments an inputArray integer array and an elementToRemove integer.

First, we find the index of the elementToRemove  integer in the inputArray array using the built-in Array.IndexOf() method.

If the elementToRemove is not found in the inputArray, we simply return the inputArray.

Otherwise, we create a new integer array tempArray with length that is one less than the inputArray array’s length. Then, we copy all elements from the original array except the elementToRemove into it using the Copy() method. Finally, we return the tempArray array.

So we end up with:

Modified Array: 4,5,3,5,7

As we expect, the new array does not include the first instance of element “3”. The remaining elements have been moved to the left and the new array has a size of five elements.

Remove First Instance of Element Using ArraySegment

Next, we can make use of the ArraySegment struct, which consists of a reference to the original array, an offset indicating the starting index of the segment in the array, and a count indicating the number of elements in the segment.

Let’s see it in action:

public int[] DeleteWithArraySegment(int[] inputArray, int elementToRemove) 
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);    

    if (indexToRemove < 0)
    {
        return inputArray;   
    }

    int[] tempArray;
    var segment1 = new ArraySegment<int>(inputArray, 0, indexToRemove);
    var segment2 = new ArraySegment<int>(inputArray, indexToRemove + 1, inputArray.Length - indexToRemove - 1);
    tempArray = segment1.Concat(segment2).ToArray();
    
    return tempArray;
}

First, we find the index position of the given element. If it does not exist, we return the inputArray array as is, as there are no elements to remove.

Otherwise, we construct two new ArraySegment objects. We create an ArraySegment object from the beginning of the inputArray to the index of the element to remove. Then, we create a second one from the right next position of the calculated index to the end of the inputArray.

Finally, we store the concatenation of these two segments into the tempArray using the Concat() method and convert the resulting IEnumerable to an array using the ToArray() method.

Use a For Loop to Remove an Element

Our next solution makes use of a loop and a temporary array:

public int[] DeleteWithLoop(int[] inputArray, int elementToRemove) 
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);

    if (indexToRemove < 0)
    {
        return inputArray;
    }

    var tempArray = new int[inputArray.Length - 1];

    for (int i = 0, j = 0; i < inputArray.Length; i++) 
    {
        if (i == indexToRemove) 
        {
            continue;
        }
        tempArray[j] = inputArray[i];
        j++;
    }

    return tempArray;                                
}

If the element does not exist in the array, we return the original inputArray. Differently, we create a new integer tempArray array of size equal to the size of inputArray decreased by one. 

Then, we use a for loop to iterate through the inputArray, copying each element to the corresponding position in tempArray except for the elementToRemove.

Finally, we return the tempArray which does not include the first instance of the specified element.

Also, we can refactor this method to use the Array.Resize() method:

public int[] DeleteWithLoop(int[] inputArray, int elementToRemove) 
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);
    if (indexToRemove >= 0) 
    {
        for (int i = indexToRemove; i < inputArray.Length - 1; i++)
        {
            inputArray[i] = inputArray[i + 1];
        }
        
        Array.Resize(ref inputArray, inputArray.Length - 1);
    }
    return inputArray;
}

Here, in the for loop, we shift every element after the indexToRemove one position to the left.

Then, we decrease the array size by one, with the use of the Array.Resize() method. To achieve this, we pass the array as a reference and the new length. 

However, we need to be cautious when we use arrays by reference. One type of issue that might arise is thread related. For example, if multiple threads access the same array that is passed by reference, it can lead to race conditions and other synchronization problems.

Remove an Element with the Use of Buffer.BlockCopy()

Also, we can use the BlockCopy() extension method of the Buffer class for removing an element:

public int[] DeleteWithBufferCopy(int[] inputArray, int elementToRemove)
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);

    if (indexToRemove < 0)
    {
        return inputArray;
    }

    var tempArray = new int[inputArray.Length - 1];

    Buffer.BlockCopy(inputArray, 0, tempArray, 0, indexToRemove * 4);

    Buffer.BlockCopy(inputArray, 
        (indexToRemove + 1) * 4, 
        tempArray, 
        indexToRemove * 4, 
        (inputArray.Length - indexToRemove - 1) * 4);

    return tempArray;
}

First, we check if the element to remove is actually in the inputArray by using the Array.IndexOf() method. If the element does not exist, we return the original inputArray. Otherwise, we create the tempArray, with a length of one less than the inputArray.

Then, we use the Buffer.BlockCopy() method to copy the elements from the inputArray into the tempArray. The first parameter is the source array, from which we copy the data. The second parameter is the starting index in the source array from where the copying starts. The third parameter is our destination array and the fourth parameter is the starting index in the destination array where we store the copied data. The last argument specifies the number of bytes to copy.

When we use the Buffer.BlockCopy() method to copy integers, we typically multiply the second, fourth, and fifth parameters by 4 to account for the fact that each integer in C# has a size of 4 bytes.

The first call to the Buffer.BlockCopy() method copies the elements before the index of the element to remove. The second call copies the elements after that index.

Finally, we return the tempArray. We use this method to efficiently remove an element from an array without having to manually shift elements around.

Delete Multiple Elements With the Where() Extension

Next, we can use the Where() extension method of LINQ:

public int[] DeleteWithWhere(int[] inputArray, int elementToRemove)
{
   return inputArray.Where(e => e != elementToRemove).ToArray();
} 

Here, we use the Where() extension method to filter out all elements from the input array that are not equal to the elementToRemove variable.

Subsequently, we convert the resulting sequence of elements back to an integer array using the ToArray() method and we return it.

We achieve the same result as the previous methods, but with a more concise syntax, using LINQ.

FindAll() Extension to Delete Array Elements

Another similar approach is with the FindAll() extension method:

public int[] DeleteWithFindAll(int[] inputArray, int elementToRemove)
{
    return Array.FindAll(inputArray, i => i != elementToRemove);
}

Here, we use the FindAll() method of the Array class to return all elements from the input array that are not equal to the elementToRemove value.

Use the RemoveAll() Extension

We can achieve the same results for deleting elements from an array by using the RemoveAll() method:

public int[] DeleteWithRemoveAll(int[] inputArray, int elementToRemove)
{
    var list = new List<int>(inputArray);
    list.RemoveAll(e => e == elementToRemove);

    return list.ToArray();
}

First, we create a new List<int>() object from the inputArray array argument.

Then we use the RemoveAll() method of the List<T> class to remove all elements in the list that are equal to the elementToRemove.

Finally, we return the list back to an integer array using again the ToArray() method. 

Use a For Loop and a List() to Remove Multiple Elements

Here, we can make use of a for loop and a List collection to remove elements:

public int[] DeleteWithList(int[] inputArray, int elementToRemove)
{
    var indexToRemove = Array.IndexOf(inputArray, elementToRemove);

    if (indexToRemove < 0)
    {
        return inputArray;
    }

    var list = new List<int>(inputArray.Length);

    for (int i = 0; i < inputArray.Length; i++)
    {
        if (inputArray[i] != elementToRemove)
        {
            list.Add(inputArray[i]);
        }
    }

    return list.ToArray();
}

After we check if the element exists in our input source array, we create a new List<int> object with an initial capacity equal to the length of the inputArray.

Then, we use a for loop to iterate through each element of the inputArray. If the examined element is not equal to the elementToRemove, it is added to the list using the List<T>.Add() method.

Finally, we return the new integer array using the List<T>.ToArray() method. The resulting array contains all the elements of the original inputArray except for the elementToRemove.

Use ArrayPool To Remove Multiple Elements

We can take advantage of using the array from the ArrayPool to skip a buffer allocation in comparison with the List option:

public static int[] DeleteWithPooledArray(int[] source, int elementToRemove)
{
    var tempArray = ArrayPool<int>.Shared.Rent(source.Length);
    try
    {
        var tempSpan = tempArray.AsSpan();
        var index = 0;
        foreach (var element in source.AsSpan())
        {
            if (element != elementToRemove) tempSpan[index++] = element;
        }

        return tempSpan[0..index].ToArray();
    }
    finally
    {
        ArrayPool<int>.Shared.Return(tempArray);
    }
}

We can even improve this code by installing the CommunityToolkit.HighPerformance NuGet package, which enables cleaner work with ArrayPool.

A big thanks to Jeff S. who suggested this solution in the comment section.

What’s the Fastest Way to Delete an Element From an Array?

We will evaluate these methods to find the most efficient one in terms of speed, with the benchmark class. Let’s create a method to use in our benchmark:

private int[] FillArray() 
{
    var rnd = new Random();
    var myArray = new int[1000];

    for (int i = 0; i < 1000; i++) 
    {
        myArray[i] = rnd.Next(1, 10);
    }

    return myArray;
}

Here, we return a random integer array of length 1000 using the .NET Random class, with each element of the array being a random number between 1 and 10.

We benchmark our suggested solutions by removing an element from the generated array accordingly.

First, let’s evaluate the methods that remove only the first instance of the element:

|                 Method |       Mean |     Error |    StdDev |     Median | Rank |   Gen0 | Allocated |
|----------------------- |-----------:|----------:|----------:|-----------:|-----:|-------:|----------:|
|    DeleteWithArrayCopy |   681.6 ns |  29.78 ns |  81.52 ns |   668.5 ns |    1 | 2.5635 |   3.93 KB |
|   DeleteWithBufferCopy |   805.0 ns |  52.13 ns | 149.57 ns |   732.5 ns |    2 | 2.5635 |   3.93 KB |
| DeleteWithArraySegment |   876.8 ns |  17.48 ns |  43.21 ns |   860.0 ns |    3 | 2.6722 |    4.1 KB |
|         DeleteWithLoop | 1,987.0 ns |  39.90 ns |  49.00 ns | 1,991.5 ns |    4 | 2.5635 |   3.93 KB |

We observe that the DeleteWithArrayCopy() method is the fastest when it comes to removing only the first element of the sequence. It uses the Array.Copy() method twice to create a new array without the removed element.

This approach avoids looping through the input array and copying elements one by one, which can be slow. It uses a built-in method that can copy large blocks of memory efficiently. 

Also, if we check the reference code of the Buffer.BlockCopy() method, we are advised to use the Array.Copy() method when we manipulate traditional array element indices. 

So, when we want to remove only one instance of an element from an array, the most efficient way is to use the DeleteWithArrayCopy() method.

Now, let’s benchmark the solutions that remove every instance from the given array:

|                 Method |       Mean |     Error |    StdDev |     Median | Rank |   Gen0 | Allocated |
|----------------------- |-----------:|----------:|----------:|-----------:|-----:|-------:|----------:|
| DeleteWithPooledArray  | 2,485.6 ns |  29.52 ns |  76.20 ns | 1,477.8 ns |    1 | 0.8602 |   3.52 KB |
|         DeleteWithList | 4,822.8 ns |  75.13 ns |  58.66 ns | 4,833.1 ns |    2 | 4.8752 |   7.48 KB |
|        DeleteWithWhere | 6,832.8 ns |  90.52 ns |  84.68 ns | 6,808.8 ns |    3 | 5.1575 |   7.91 KB |
|    DeleteWithRemoveAll | 7,385.0 ns | 130.32 ns | 133.83 ns | 7,351.6 ns |    4 | 4.8523 |   7.45 KB |
|      DeleteWithFindAll | 8,010.4 ns | 134.15 ns | 125.49 ns | 8,016.9 ns |    5 | 7.6904 |   11.8 KB |

When it comes to deleting multiple elements, the DeleteWithPooledArray() method seems to be the winner.

The methods that use LINQ such as DeleteWithRemoveAll() and DeleteWithWhere() include lambda expressions and delegates to define the condition for removing elements, which adds some overhead compared to the other methods.

Conclusion

In this article, we looked at eight different methods that allow us to delete elements from an array. Then, we evaluated our solutions in terms of performance and efficiency, determining which was the best choice to suit our requirements.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!