在C#中追加数组最有效的方法?

我正在用双数组的forms从老派的ActiveX中提取数据。 我最初并不知道最终的实际样本数量。

在C#中将这些数组连接在一起的最有效方法是什么?

你不能附加到实际的数组 – 在创build时数组的大小是固定的。 相反,使用List<T> ,它可以根据需要增长。

或者,保存一个数组列表,并将它们连接在一起,只有当你抓住所有东西。

有关详细信息和洞察力,请参阅Eric Lippert关于数组的博客文章,而不是我实际上可以提供的:)

我相信,如果你有两个相同types的数组,你想合并成第三个数组,有一个非常简单的方法来做到这一点。

这是代码:

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

我build议在这里find的答案: 我如何在C#中连接两个数组?

例如

 var z = new int[x.Length + y.Length]; x.CopyTo(z, 0); y.CopyTo(z, x.Length); 

使用.Net 4标准的linq扩展来连接数组很简单

要记住的最大的事情是linq与IEnumerable<T>对象一起工作,所以为了得到一个数组作为结果,那么你必须在.ToArray()使用.ToArray()方法

连接两个字节数组的示例:

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

该解决scheme看起来非常有趣,但可以用两个语句连接数组。 在处理大型字节数组时,我认为使用链表来包含每个字节是低效的。

下面是一个代码示例,用于从stream中读取字节并实时扩展字节数组:

     byte [] buf = new byte [8192];
     byte []结果=新字节[0];
     int count = 0;
    做
     {
         count = resStream.Read(buf,0,buf.Length);
        如果(count!= 0)
         {
             Array.Resize(ref result,result.Length + count);
             Array.Copy(buf,0,result,result.Length  -  count,count);
         }
     }
     while(count> 0);  //还有更多数据要读取?
     resStream.Close();

使用这个我们可以添加任何循环的两个数组。

我相信,如果你有两个相同types的数组,你想合并成一个数组,有一个非常简单的方法来做到这一点。

代码如下:

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

如果您可以近似地计算最后将出现的项目数,请使用以count为参数的List构造函数的重载。 您将节省一些昂贵的列表重复。 否则,你必须付钱。

您可能不需要将最终结果连接成连续的数组。 相反,不要像Jonbuild议的那样追加到列表中。 最后你会有一个锯齿状的数组 (事实上​​,几乎是矩形的)。 当您需要通过索引访问元素时,请使用以下索引scheme:

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

这样可以节省你的内存分配和复制,但是要稍微慢一点的元素访问。 这是否会成为净收益取决于您的数据大小,数据访问模式和内存限制。

这是一个可用的类,根据康斯坦丁说:

 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 } 

奥尔莫的build议是非常好的,但我想补充一点:如果你不确定这个尺寸,最好稍大一点。 当列表已满时,请记住它会将其大小加倍以添加更多元素。

例如:假设你将需要大约50个元素。 如果您使用50个元素大小,最后一个元素数量为51,那么您将以100个大小的列表结束,其中包含49个浪费的位置。