Удалить элемент регулярного массива

У меня есть массив объектов Foo. Как удалить второй элемент массива?

Мне нужно что-то похожее на RemoveAt(), но для регулярного массива.

Ответ 1

Если вы не хотите использовать List:

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

Вы можете попробовать этот метод расширения, который я на самом деле не тестировал:

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

И используйте его как:

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

Ответ 2

Характер массивов состоит в том, что их длина неизменна. Вы не можете добавлять или удалять элементы массива.

Вам нужно будет создать новый массив, который будет короче одного элемента и скопировать старые элементы в новый массив, исключая элемент, который вы хотите удалить.

Поэтому лучше использовать список вместо массива.

Ответ 3

Я использую этот метод для удаления элемента из массива объектов. В моей ситуации мои массивы имеют небольшую длину. Поэтому, если у вас есть большие массивы, вам может понадобиться другое решение.

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

Ответ 4

Однострочное решение LINQ:

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

1 в этом примере - это индекс элемента для удаления - в этом примере, в исходном вопросе, второй элемент (с 1 является вторым элементом в индексировании массива с нулевой матрицей на С#).

Более полный пример:

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

После запуска этого фрагмента значение myArray будет { "a", "c", "d", "e" }.

Ответ 5

Это способ удаления элемента массива с .Net 3.5 без копирования в другой массив - с использованием того же экземпляра массива с 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 decrement Array size by one
    Array.Resize(ref arr, arr.Length - 1);
}

Ответ 6

Вот старая версия, которая работает в версии 1.0 .NET и не нуждается в общих типах.

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

Это используется следующим образом:

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

Ответ 7

Не совсем так, как это сделать, но если ситуация тривиальна и вы цените свое время, вы можете попробовать это для типов с нулевым значением.

Foos[index] = null

а затем проверить нулевые записи в вашей логике.

Ответ 8

Как обычно, я опаздываю на вечеринку...

Я хочу добавить еще один вариант в список доступных решений. =)
Я бы рассматривал это как хорошую возможность для расширений.

Ссылка: http://msdn.microsoft.com/en-us/library/bb311042.aspx

Итак, мы определяем некоторый статический класс и в нем наш метод.
После этого мы можем использовать наш расширенный метод волей-неволей. =)

using System;

namespace FunctionTesting {

    // The class doesn't matter, as long as it static
    public static class SomeRandomClassWhoseNameDoesntMatter {

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

Ответ 9

Вот как я это сделал...

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

Ответ 10

В обычном массиве вам нужно перетасовать все элементы массива выше 2 и затем изменить его размер с помощью метода Resize. Возможно, вам лучше использовать ArrayList.

Ответ 11

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

Ответ 12

Здесь представлена ​​небольшая коллекция вспомогательных методов, созданная на основе некоторых существующих ответов. Он использует как расширения, так и статические методы с опорными параметрами для максимальной идеальности:

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

Производительность мудрая, она приличная, но она, вероятно, может быть улучшена. Remove зависит от IndexOf, и создается новый массив для каждого элемента, который вы хотите удалить, вызывая RemoveAt.

IndexOf - единственный метод расширения, поскольку ему не нужно возвращать исходный массив. New принимает несколько элементов некоторого типа для создания нового массива указанного типа. Все другие методы должны принимать исходный массив в качестве ссылки, поэтому нет необходимости назначать результат после этого, поскольку это происходит уже внутри.

Я бы определил метод Merge для слияния двух массивов; однако это уже можно выполнить с помощью метода Add, передавая фактический массив по сравнению с несколькими отдельными элементами. Поэтому Add может использоваться двумя способами для объединения двух наборов элементов:

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

Или

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

Ответ 13

Я знаю, что этой статье десять лет и, следовательно, она, вероятно, мертва, но вот что я попробую сделать:

Используйте метод IEnumerable.Skip(), найденный в System.Linq. Он пропустит выбранный элемент из массива и вернет другую копию массива, которая содержит только все, кроме выбранного объекта. Затем просто повторите это для каждого элемента, который вы хотите удалить, и после этого сохраните его в переменной.

Например, если у нас есть массив с именем "Sample" (типа int []) с 5 числами. Мы хотим удалить 2-й, поэтому пробуем "Sample.Skip(2);" должен вернуть тот же массив, кроме как без 2-го числа.

Ответ 14

Попробуйте код ниже:

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

или

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

Ответ 15

Первый шаг
Вам нужно преобразовать массив в список, вы можете написать метод расширения, подобный этому

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

Второй шаг
Напишите метод расширения для преобразования списка в массив

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

Последние шаги
Напишите свой последний метод, но не забудьте удалить элемент по индексу перед тем, как преобразовать его обратно в массив, например, show code

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

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

коды примеров можно найти на в моем блоге, отслеживать.