2009-01-19 72 views
90

我有一個Foo對象的數組。如何刪除數組的第二個元素?刪除常規數組的元素

我需要類似於RemoveAt()的東西,但對於一個常規數組。

+0

使用`System.Collections.ObjectModel.Collection `。 – abatishchev 2009-01-19 12:46:27

+0

對於我的遊戲,我使用了「null at index」數據結構。基本上,內部數組(緩衝區)是靜態大小,而不是刪除索引和調整數組大小,我只是使索引爲空。當我需要添加一個項目時,我只找到第一個非空索引並將其放在那裏。工作得很好,但顯然不適合所有事情。 – Krythic 2016-09-17 15:00:59

回答

148

如果你不想使用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); 
+6

在此答案給出的第一個例子是比所述第二效率要低得多。它需要兩個陣列副本和索引之後的所有內容,而不是一個選擇性陣列副本。 – 2009-01-19 19:25:31

+1

當然+1,但我們也可以用列表太升 列表名單=新名單(GetFoos()); list.Remove(my_foo); list.RemoveAt(2); GetFoos()將返回Foos數組! – shahjapan 2009-12-18 10:28:45

+1

方法內的第一行應該說'source.Length'而不是'array.Length'。 – Nelson 2010-08-06 17:17:13

1

這裏是我是如何做到的?

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

陣列的本質是它們的長度是不變的。您不能添加或刪除任何數組項目。

您將不得不創建一個短一個元素的新數組,並將舊項目複製到新數組中,但不包括要刪除的元素。

因此,最好使用List而不是數組。

+3

陣列轉換到列表`列表陣列=新列表(arrayofmydatatype)` – 2013-02-15 09:16:26

1

在普通數組中,您必須將所有大於2的數組輸入進行混洗,然後使用Resize方法調整它的大小。使用ArrayList可能會更好。

5

這是一箇舊版本,它適用於.NET框架的1.0版本,並且不需要generi c類型。

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

我使用用於從一個對象數組移除元素此方法。在我的情況下,我的陣列長度很小。所以如果你有大陣列,你可能需要另一種解決方案。

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

不完全相同的方式去了解這一點,但如果情況是瑣碎和你珍惜你的時間,你可以嘗試一下本作空類型。

Foos[index] = null 

和更高版本檢查邏輯中的空條目..

-4

第一步
您需要將數組轉換成列表,你可以這樣寫

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

例子代碼可以在my blog被發現,保持跟蹤。

7

這是刪除一個數組元素,如淨3.5的一種方式,而不會複製到另一個陣列 - 使用相同的陣列實例與Array.Resize<T>

​​
2

像往常一樣,我遲到了派對......

我想添加另一個選項到已經存在的很好的解決方案列表中。 =)
我認爲這是擴展的好機會。

參考: 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" 
      */ 
     } 
    } 
} 
31

LINQ單行溶液:

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

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

下面是我根據一些現有答案生成的一小組幫助方法。它利用兩個擴展和靜態方法與最大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; 
    } 
} 

在性能方面,它是體面的,但它很可能得到改善。Remove依靠IndexOf和要通過調用RemoveAt刪除的每個元素創建一個新的陣列。

IndexOf是因爲它並不需要返回原始數組的唯一擴展方法。 New接受某種類型的多個元素來產生一個新的這種類型的數組。所有其他方法必須接受原始數組作爲參考,所以不需要在後面分配結果,因爲這已經在內部發生了。

我已經定義了一個Merge方法用於合併兩個陣列;然而,通過傳遞一個實際的數組與多個單獨的元素,已經可以用Add方法完成。因此,Add可以通過以下兩種方式來連接兩個組元素:

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

或者

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