删除常规数组的元素

我有一个Foo对象的数组。 如何删除数组的第二个元素?

我需要类似于RemoveAt()东西,但对于一个普通的数组。

如果你不想使用列表:

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

你可以试试这个我没有真正testing的扩展方法:

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

数组的本质是它们的长度是不变的。 您不能添加或删除任何数组项目。

您将不得不创build一个短一个元素的新数组,并将旧项目复制到新数组中,不包括要删除的元素。

所以最好使用List而不是数组。

我使用这种方法从对象数组中删除元素。 在我的情况下,我的arrays长度很小。 所以,如果你有大型数组,你可能需要另一种解决scheme

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

LINQ单线解决scheme:

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

该示例中的1是要删除的元素的索引 – 在本例中,按原始问题,第二个元素(其中1是C#中从零开始的数组索引中的第二个元素)。

一个更完整的例子:

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

运行该代码片段之后, myArray的值将是{ "a", "c", "d", "e" }

这是一种删除数据元素的方法,从.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's decrement Array's size by one Array.Resize(ref arr, arr.Length - 1); } 

这是我有一个旧版本的.NET框架的1.0版本,不需要genericstypes。

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

不完全是这样的方式,但如果情况微不足道,而且你重视你的时间,你可以试试这个可为空的types。

 Foos[index] = null 

然后检查逻辑中的空条目

像往常一样,我迟到了…

我想添加另一个选项,已经出现在很好的解决scheme列表中。 =)
我认为这是扩展的好机会。

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

所以,我们定义一些静态类,并在其中,我们的方法。
之后,我们可以使用我们的扩展方法。 =)

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

我是这么做的

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

在一个正常的数组中,你必须将所有大于2的数组进行混洗,然后使用Resize方法调整它的大小。 使用ArrayList可能会更好。

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

下面是我根据现有的一些答案制作的小帮手方法集合。 它利用扩展和静态方法和参考参数来实现最大的理想度:

 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为每个要删除的元素创build一个新的数组。

IndexOf是唯一的扩展方法,因为它不需要返回原始数组。 New接受某种types的多个元素来产生一个新的这种types的数组。 所有其他方法都必须接受原始数组作为参考,因此不需要在之后的内部分配结果。

我会定义合并两个数组的方法; 不过,通过传入一个实际的数组与多个单独的元素,可以使用Add方法来完成。 所以Add可以用以下两种方式来连接两组元素:

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

要么

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

第一步
你需要将数组转换成列表,你可以写这样的扩展方法

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

最后一步
编写你的最后一个方法,但记得在转换回像数组代码的数组之前删除索引处的元素

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

示例代码可以在我的博客上find,保持跟踪。