Использование System.Collections.ObjectModel.Collection<Foo>.
abatishchev
1
В своей игре я использовал структуру данных с нулевым индексом. По сути, внутренний массив (буфер) имеет статический размер, и вместо удаления индекса и изменения размера массива я просто делаю индекс нулевым. Когда мне нужно добавить элемент, я просто нахожу первый ненулевой индекс и помещаю его туда. Работает неплохо, но не для всего.
Krythic,
Ответы:
202
Если вы не хотите использовать список:
var foos =newList<Foo>(array);
foos.RemoveAt(index);return foos.ToArray();
Вы можете попробовать этот метод расширения, который я еще не тестировал:
publicstatic 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;}
Первый пример, приведенный в этом ответе, намного менее эффективен, чем второй. Для этого требуется две копии массива и сдвиг всего после индекса, а не одна выборочная копия массива.
Мартин Браун
2
+1, конечно, но мы также можем использовать список OR List <Foo> list = new List <Foll> (GetFoos ()); list.Remove (my_foo); list.RemoveAt (2); где GetFoos () вернет массив Foos !!!!
Shahjapan
2
Первая строка внутри метода должна содержать «source.Length» вместо «array.Length».
Нельсон
1
Кроме того, имейте в виду, что любая переменная, хранящая ссылку на исходный массив, будет по-прежнему содержать исходные данные и что любое сравнение равенства ссылок между массивом в источнике и выходным массивом будет возвращать отрицательное значение.
bkqc 05
1
@MartinBrown На самом деле преобразование списка в \ from и массив происходит намного медленнее, чем копирование массива (которое может копировать данные с максимальной скоростью, разрешенной ЦП, всего с несколькими инструкциями ASM). Кроме того, смещение списка происходит очень быстро, потому что это просто вопрос замены нескольких указателей и удаления данных узла (в данном случае это всего 8 байт [плюс еще 16 для указателей головы / хвоста]).
krowe2
66
Природа массивов такова, что их длина неизменна. Вы не можете добавлять или удалять какие-либо элементы массива.
Вам нужно будет создать новый массив на один элемент короче и скопировать старые элементы в новый массив, за исключением элемента, который вы хотите удалить.
Так что, вероятно, лучше использовать список вместо массива.
Преобразование массива в списокList<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
Immortal Blue
1
@ImmortalBlue или просто var myList = myArray.ToList();используя Enumerable.ToList()метод из System.Linqпространства имен.
Dyndrilliac
58
Я использую этот метод для удаления элемента из массива объектов. В моей ситуации мои массивы малы по длине. Так что, если у вас большие массивы, вам может понадобиться другое решение.
Лично мне этот ответ нравится больше, чем принятый. Он должен быть таким же эффективным, и его намного легче читать. Я могу смотреть на него и знать, что это правильно. Мне пришлось бы протестировать другой, чтобы убедиться, что эти копии написаны правильно.
oillio 08
1
Очень жаль, что этот ответ настолько низкий, хотя он намного лучше, чем два выше.
Sepulchritude
Aaarhg, это тот ответ, который я искал! Это лучший способ без списков.
Хорди Уэртас,
47
Однострочное решение LINQ:
myArray = myArray.Where((source, index)=> index !=1).ToArray();
В 1этом примере это индекс удаляемого элемента - в этом примере, согласно исходному вопросу, это 2-й элемент ( 1который является вторым элементом в индексировании массива C # с отсчетом от нуля).
Для областей, требующих высокой производительности / частого доступа, LINQ не рекомендуется.
Krythic
3
@Krythic Это честный комментарий. Выполнение этого решения тысячи раз в жестком цикле не так хорошо, как у некоторых других решений на этой странице, получивших большое количество голосов
Jon Schneider
9
Это способ удалить элемент массива, начиная с .Net 3.5, без копирования в другой массив - используя тот же экземпляр массива с Array.Resize<T>:
publicstaticvoidRemoveAt<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 oneArray.Resize(ref arr, arr.Length-1);}
«без копирования в другой массив» - в связанной документации, Array.Resize фактически делает выделить новый массив за кулисами, и копирует элементы из старого массива в новый. Тем не менее, мне нравится лаконичность этого решения.
Jon Schneider
Очень красиво и понятно, если вы уверены, что это относительно небольшой массив.
Даррен
1
Продолжая комментарий @JonSchneider, это не «тот же экземпляр массива». Вот почему вам нужно использовать refпри вызове Resizeметода. Длина экземпляра массива фиксирована и неизменна.
Джеппе Стиг Нильсен
2
Если порядок элементов не важен, вместо перемещения всех элементов вниз вы можете поменять местами элемент по индексу с последним элементом, а затем изменить размер: arr [index] = arr [arr.Length - 1]; Array.Resize (ref arr, arr.Length - 1);
Бартель
5
Вот моя старая версия, которая работает с версией 1.0 платформы .NET и не требует общих типов.
publicstaticArrayRemoveAt(Array source,int index){if(source ==null)thrownewArgumentNullException("source");if(0> index || index >= source.Length)thrownewArgumentOutOfRangeException("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;}
Это используется так:
classProgram{staticvoidMain(string[] args){string[] x =newstring[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]);}}
publicstaticElementDefinitionImpl[]RemoveElementDefAt(ElementDefinition[] oldList,int removeIndex
){ElementDefinitionImpl[] newElementDefList =newElementDefinitionImpl[ oldList.Length-1];int offset =0;for(int index =0; index < oldList.Length; index++){ElementDefinitionImpl elementDef = oldList[ index ]asElementDefinitionImpl;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;}
В обычном массиве вы должны перетасовать все элементы массива выше 2, а затем изменить его размер с помощью метода Resize. Возможно, вам лучше использовать ArrayList.
Вот небольшая коллекция вспомогательных методов, которые я создал на основе некоторых из существующих ответов. Он использует как расширения, так и статические методы с эталонными параметрами для максимальной идеальности:
publicstaticclassArr{publicstaticintIndexOf<TElement>(thisTElement[]Source,TElementElement){for(var i =0; i <Source.Length; i++){if(Source[i].Equals(Element))return i;}return-1;}publicstaticTElement[]Add<TElement>(refTElement[]Source,paramsTElement[]Elements){varOldLength=Source.Length;Array.Resize(refSource,OldLength+Elements.Length);for(int j =0,Count=Elements.Length; j <Count; j++)Source[OldLength+ j]=Elements[j];returnSource;}publicstaticTElement[]New<TElement>(paramsTElement[]Elements){returnElements??newTElement[0];}publicstaticvoidRemove<TElement>(refTElement[]Source,paramsTElement[]Elements){foreach(var i inElements)RemoveAt(refSource,Source.IndexOf(i));}publicstaticvoidRemoveAt<TElement>(refTElement[]Source,intIndex){varResult=newTElement[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для соединения двух наборов элементов могут использоваться следующие два способа:
Я знаю, что этой статье десять лет и, следовательно, она, вероятно, мертва, но вот что я попробую сделать:
Используйте метод IEnumerable.Skip (), найденный в System.Linq . Он пропустит выбранный элемент из массива и вернет другую копию массива, которая содержит только все, кроме выбранного объекта. Затем просто повторите это для каждого элемента, который вы хотите удалить, и после этого сохраните его в переменной.
Например, если у нас есть массив с именем «Sample» (типа int []) с 5 числами. Мы хотим удалить второй, поэтому пробуем "Sample.Skip (2);" должен возвращать тот же массив, за исключением второго числа.
Разве этот метод не просто обходит указанное количество элементов в последовательности, а затем возвращает оставшиеся элементы ? В вашем примере вы «пропустите» первые два элемента общего списка, а не только второй!
xnr_z
-4
Первый шаг.
Вам нужно преобразовать массив в список, вы можете написать такой метод расширения.
// Convert An array of string to a list of stringpublicstaticList<string>ConnvertArrayToList(thisstring[]array){// DECLARE a list of string and add all element of the array into itList<string> myList =newList<string>();foreach(string s inarray){
myList.Add(s);}return myList;}
Второй шаг
Напишите метод расширения для обратного преобразования списка в массив
// convert a list of string to an array publicstaticstring[]ConvertListToArray(thisList<string>list){string[]array=newstring[list.Capacity];array=list.Select(i => i.ToString()).ToArray();returnarray;}
Последние шаги
Напишите свой последний метод, но не забудьте удалить элемент по индексу перед преобразованием обратно в массив, как показано в коде
System.Collections.ObjectModel.Collection<Foo>
.Ответы:
Если вы не хотите использовать список:
Вы можете попробовать этот метод расширения, который я еще не тестировал:
И используйте это как:
источник
Природа массивов такова, что их длина неизменна. Вы не можете добавлять или удалять какие-либо элементы массива.
Вам нужно будет создать новый массив на один элемент короче и скопировать старые элементы в новый массив, за исключением элемента, который вы хотите удалить.
Так что, вероятно, лучше использовать список вместо массива.
источник
List<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
var myList = myArray.ToList();
используяEnumerable.ToList()
метод изSystem.Linq
пространства имен.Я использую этот метод для удаления элемента из массива объектов. В моей ситуации мои массивы малы по длине. Так что, если у вас большие массивы, вам может понадобиться другое решение.
источник
Однострочное решение LINQ:
В
1
этом примере это индекс удаляемого элемента - в этом примере, согласно исходному вопросу, это 2-й элемент (1
который является вторым элементом в индексировании массива C # с отсчетом от нуля).Более полный пример:
После запуска этого фрагмента значение
myArray
будет{ "a", "c", "d", "e" }
.источник
Это способ удалить элемент массива, начиная с .Net 3.5, без копирования в другой массив - используя тот же экземпляр массива с
Array.Resize<T>
:источник
ref
при вызовеResize
метода. Длина экземпляра массива фиксирована и неизменна.Вот моя старая версия, которая работает с версией 1.0 платформы .NET и не требует общих типов.
Это используется так:
источник
Не совсем так, но если ситуация тривиальна и вы цените свое время, вы можете попробовать это для типов, допускающих значение NULL.
а затем проверьте наличие нулевых записей в вашей логике.
источник
Я как обычно опаздываю на вечеринку ...
Я хотел бы добавить еще один вариант в уже имеющийся список хороших решений. =)
Я бы увидел в этом хорошую возможность для расширений.
Ссылка: http://msdn.microsoft.com/en-us/library/bb311042.aspx
Итак, мы определяем некоторый статический класс и в нем наш метод.
После этого мы волей-неволей можем использовать наш расширенный метод. знак равно
источник
Попробуйте код ниже:
или
источник
Вот как я это сделал ...
источник
В обычном массиве вы должны перетасовать все элементы массива выше 2, а затем изменить его размер с помощью метода Resize. Возможно, вам лучше использовать ArrayList.
источник
источник
Вот небольшая коллекция вспомогательных методов, которые я создал на основе некоторых из существующих ответов. Он использует как расширения, так и статические методы с эталонными параметрами для максимальной идеальности:
По производительности он неплохой, но, вероятно, его можно было бы улучшить.
Remove
полагается,IndexOf
и новый массив создается для каждого элемента, который вы хотите удалить с помощью вызоваRemoveAt
.IndexOf
- единственный метод расширения, поскольку ему не нужно возвращать исходный массив.New
принимает несколько элементов определенного типа для создания нового массива указанного типа. Все другие методы должны принимать исходный массив в качестве ссылки, поэтому нет необходимости назначать результат позже, поскольку это уже происходит внутри.Я бы определил
Merge
метод слияния двух массивов; однако это уже может быть выполнено с помощьюAdd
метода путем передачи фактического массива вместо нескольких отдельных элементов. Следовательно,Add
для соединения двух наборов элементов могут использоваться следующие два способа:Или
источник
Я знаю, что этой статье десять лет и, следовательно, она, вероятно, мертва, но вот что я попробую сделать:
Используйте метод IEnumerable.Skip (), найденный в System.Linq . Он пропустит выбранный элемент из массива и вернет другую копию массива, которая содержит только все, кроме выбранного объекта. Затем просто повторите это для каждого элемента, который вы хотите удалить, и после этого сохраните его в переменной.
Например, если у нас есть массив с именем «Sample» (типа int []) с 5 числами. Мы хотим удалить второй, поэтому пробуем "Sample.Skip (2);" должен возвращать тот же массив, за исключением второго числа.
источник
Первый шаг.
Вам нужно преобразовать массив в список, вы можете написать такой метод расширения.
Второй шаг
Напишите метод расширения для обратного преобразования списка в массив
Последние шаги
Напишите свой последний метод, но не забудьте удалить элемент по индексу перед преобразованием обратно в массив, как показано в коде
примеры кодов можно найти в моем блоге , продолжайте отслеживать.
источник
.ToArray()
иList<T>
конструктор , который принимает существующую последовательность ...