2008-11-20 38 views
54

我正在以double數組的形式從老派的ActiveX中拉出數據。我最初並不知道我將實際檢索的樣本的最終數量。在C#中追加數組的最有效方法?

當我將它們拉出系統時,將這些數組連接在一起的最有效方法是什麼?

+1

是相同或不同尺寸的這些陣列的樣品? – Constantin 2008-11-20 11:55:13

回答

69

您不能附加到實際數組 - 創建時數組的大小是固定的。相反,使用可以根據需要增長的List<T>

或者,保留一個數組列表,並將它們連接在一起,只有當你抓住所有東西。

更多細節和洞察見Eric Lippert's blog post on arrays比我能切實提供:)

4

如果你能做出還會在月底的項目數的近似,使用List constuctor,它利用過載算作參數。您將節省一些昂貴的List副本。否則,你必須付錢。

0

奧爾莫的建議是非常好的,但我想補充一點: 如果你不確定尺寸,最好稍大一點。當列表已滿時,請記住它會將其大小加倍以添加更多元素。

例如:假設您將需要約50個元素。如果您使用50個元素大小,並且最終元素數量爲51,那麼您將以100個大小的列表結束,其中49個位置浪費。

4

您可能不需要將最終結果連接成連續數組。相反,請繼續追加到Jon建議的列表中。最後你會有一個jagged array(事實上,幾乎是矩形)。當你需要通過索引來訪問一個元素,可以使用以下索引方案:

double x = list[i/sampleSize][i % sampleSize]; 

迭代超過交錯數組也很簡單:

for (int iRow = 0; iRow < list.Length; ++iRow) { 
    double[] row = list[iRow]; 
    for (int iCol = 0; iCol < row.Length; ++iCol) { 
    double x = row[iCol]; 
    } 
} 

這在稍慢元的費用可以節省內存的分配和複製訪問。這是否會成爲淨績效取決於數據大小,數據訪問模式和內存限制。

2

這裏是一個可用的階級基礎是什麼康斯坦丁說:

class Program 
{ 
    static void Main(string[] args) 
    { 
     FastConcat<int> i = new FastConcat<int>(); 
     i.Add(new int[] { 0, 1, 2, 3, 4 }); 
     Console.WriteLine(i[0]); 
     i.Add(new int[] { 5, 6, 7, 8, 9 }); 
     Console.WriteLine(i[4]); 

     Console.WriteLine("Enumerator:"); 
     foreach (int val in i) 
      Console.WriteLine(val); 

     Console.ReadLine(); 
    } 
} 

class FastConcat<T> : IEnumerable<T> 
{ 
    LinkedList<T[]> _items = new LinkedList<T[]>(); 
    int _count; 

    public int Count 
    { 
     get 
     { 
      return _count; 
     } 
    } 

    public void Add(T[] items) 
    { 
     if (items == null) 
      return; 
     if (items.Length == 0) 
      return; 

     _items.AddLast(items); 
     _count += items.Length; 
    } 

    private T[] GetItemIndex(int realIndex, out int offset) 
    { 
     offset = 0; // Offset that needs to be applied to realIndex. 
     int currentStart = 0; // Current index start. 

     foreach (T[] items in _items) 
     { 
      currentStart += items.Length; 
      if (currentStart > realIndex) 
       return items; 
      offset = currentStart; 
     } 
     return null; 
    } 

    public T this[int index] 
    { 
     get 
     { 
      int offset; 
      T[] i = GetItemIndex(index, out offset); 
      return i[index - offset]; 
     } 
     set 
     { 
      int offset; 
      T[] i = GetItemIndex(index, out offset); 
      i[index - offset] = value; 
     } 
    } 

    #region IEnumerable<T> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     foreach (T[] items in _items) 
      foreach (T item in items) 
       yield return item; 
    } 

    #endregion 

    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    #endregion 
} 
6

的解決方案看起來很有趣,但它有可能來連接陣列在短短的語句。在處理大型字節數組時,我認爲使用鏈表來包含每個字節效率不高。

下面是從流在飛行中讀取字節和延伸的字節數組代碼示例:

 
    byte[] buf = new byte[8192]; 
    byte[] result = new byte[0]; 
    int count = 0; 
    do 
    { 
     count = resStream.Read(buf, 0, buf.Length); 
     if (count != 0) 
     { 
      Array.Resize(ref result, result.Length + count); 
      Array.Copy(buf, 0, result, result.Length - count, count); 
     } 
    } 
    while (count > 0); // any more data to read? 
    resStream.Close(); 
24

我相信如果你有2個陣列相同類型的要合併成第三數組,有一個非常簡單的方法來做到這一點。

下面的代碼:

String[] theHTMLFiles = Directory.GetFiles(basePath, "*.html"); 
String[] thexmlFiles = Directory.GetFiles(basePath, "*.xml"); 
List<String> finalList = new List<String>(theHTMLFiles.Concat<string>(thexmlFiles)); 
String[] finalArray = finalList.ToArray(); 
17

串聯陣列是簡單的使用LINQ擴展,並標配了.NET 4中

記住

最重要的事情是,LINQ可與IEnumerable<T>對象,所以爲了得到一個數組早在你的結果,那麼你必須在最後使用.ToArray()方法

實施例連接兩個字節陣列的:

byte[] firstArray = {2,45,79,33}; 
byte[] secondArray = {55,4,7,81}; 
byte[] result = firstArray.Concat(secondArray).ToArray(); 
6

使用這個我們可以添加兩個數組與任何循環。

我相信如果你有2個陣列相同類型的要合併到陣列中的一個,有一個很簡單的方法來做到這一點。

下面的代碼:

String[] TextFils = Directory.GetFiles(basePath, "*.txt"); 
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls"); 
String[] finalArray = TextFils.Concat(ExcelFils).ToArray(); 

String[] Fils = Directory.GetFiles(basePath, "*.txt"); 
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls"); 
Fils = Fils.Concat(ExcelFils).ToArray(); 
相關問題