在.NET中合并两个数组
有没有在.NET 2.0中的内置函数,将采取两个数组,并将它们合并成一个数组?
数组都是相同的types。 我从我的代码库中广泛使用的函数中获取这些数组,并且不能修改函数以不同的格式返回数据。
我正在寻求避免写我自己的function,如果可能的话就做到这一点。
如果您可以操作其中一个数组,则可以在执行复制之前调整它的大小:
T[] array1 = getOneArray(); T[] array2 = getAnotherArray(); int array1OriginalLength = array1.Length; Array.Resize<T>(ref array1, array1OriginalLength + array2.Length); Array.Copy(array2, 0, array1, array1OriginalLength, array2.Length);
否则,你可以创build一个新的数组
T[] array1 = getOneArray(); T[] array2 = getAnotherArray(); T[] newArray = new T[array1.Length + array2.Length]; Array.Copy(array1, newArray, array1.Length); Array.Copy(array2, 0, newArray, array1.Length, array2.Length);
更多关于MSDN上可用的数组方法 。
在C#3.0中,您可以使用LINQ的Concat方法轻松完成此操作:
int[] front = { 1, 2, 3, 4 }; int[] back = { 5, 6, 7, 8 }; int[] combined = front.Concat(back).ToArray();
在C#2.0中,你没有这种直接的方式,但Array.Copy可能是最好的解决scheme:
int[] front = { 1, 2, 3, 4 }; int[] back = { 5, 6, 7, 8 }; int[] combined = new int[front.Length + back.Length]; Array.Copy(front, combined, front.Length); Array.Copy(back, 0, combined, front.Length, back.Length);
这可以很容易地用来实现你自己的Concat
版本。
使用LINQ :
var arr1 = new[] { 1, 2, 3, 4, 5 }; var arr2 = new[] { 6, 7, 8, 9, 0 }; var arr = arr1.Union(arr2).ToArray();
首先,确保你问自己这个问题:“我真的应该在这里使用数组吗?
除非你正在构build速度至关重要的东西,否则一个types化的List,比如List<int>
可能是要走的路。 我唯一一次使用数组是通过networking发送东西时的字节数组。 除此之外,我从不碰他们。
更简单的就是使用LINQ :
var array = new string[] { "test" }.ToList(); var array1 = new string[] { "test" }.ToList(); array.AddRange(array1); var result = array.ToArray();
首先将数组转换为列表并合并它们…之后,只需将列表转换回数组:)
我想你可以使用Array.Copy 。 它需要一个源索引和目标索引,所以你应该能够将一个数组附加到另一个。 如果你需要变得更复杂,而不仅仅是将一个追加到另一个,这可能不适合你。
就我个人而言,我更喜欢我自己的语言扩展,我随意添加或删除了快速原型。
以下是string的示例。
//resides in IEnumerableStringExtensions.cs public static class IEnumerableStringExtensions { public static IEnumerable<string> Append(this string[] arrayInitial, string[] arrayToAppend) { string[] ret = new string[arrayInitial.Length + arrayToAppend.Length]; arrayInitial.CopyTo(ret, 0); arrayToAppend.CopyTo(ret, arrayInitial.Length); return ret; } }
它比LINQ和Concat快得多。 更快的是,正在使用一个自定义的IEnumerable
types包装,它存储了传递数组的引用/指针,并允许在整个集合上循环,就像它是一个正常的数组。 (在HPC,graphics处理,graphics渲染中有用…)
你的代码:
var someStringArray = new[]{"a", "b", "c"}; var someStringArray2 = new[]{"d", "e", "f"}; someStringArray.Append(someStringArray2 ); //contains a,b,c,d,e,f
整个代码和generics版本请参阅: https : //gist.github.com/lsauer/7919764
注意:这将返回一个未扩展的IEnumerable对象。 返回一个扩展对象有点慢。
自2002年以来,我编译了这样的扩展,有很多学分会转给CodeProject和“Stackoverflow”上的帮助人员。 我会很快发布,并把链接放在这里。
每个人都已经有了发言权,但我认为这比“用作扩展方法”的方法更可读:
var arr1 = new[] { 1, 2, 3, 4, 5 }; var arr2 = new[] { 6, 7, 8, 9, 0 }; var arr = Queryable.Concat(arr1, arr2).ToArray();
但是它只能在将两个数组放在一起时使用。
假设目标数组有足够的空间, Array.Copy()将工作。 您也可以尝试使用List <T>及其.AddRange()方法。
如果你不想删除重复,那么试试这个
使用LINQ:
var arr1 = new[] { 1, 2, 3, 4, 5 }; var arr2 = new[] { 6, 7, 8, 9, 0 }; var arr = arr1.Concat(arr2).ToArray();
如果有人正在寻找如何合并两个图像字节数组:
private void LoadImage() { string src = string.empty; byte[] mergedImageData = new byte[0]; mergedImageData = MergeTwoImageByteArrays(watermarkByteArray, backgroundImageByteArray); src = "data:image/png;base64," + Convert.ToBase64String(mergedImageData); MyImage.ImageUrl = src; } private byte[] MergeTwoImageByteArrays(byte[] imageBytes, byte[] imageBaseBytes) { byte[] mergedImageData = new byte[0]; using (var msBase = new MemoryStream(imageBaseBytes)) { System.Drawing.Image imgBase = System.Drawing.Image.FromStream(msBase); Graphics gBase = Graphics.FromImage(imgBase); using (var msInfo = new MemoryStream(imageBytes)) { System.Drawing.Image imgInfo = System.Drawing.Image.FromStream(msInfo); Graphics gInfo = Graphics.FromImage(imgInfo); gBase.DrawImage(imgInfo, new Point(0, 0)); //imgBase.Save(Server.MapPath("_____testImg.png"), ImageFormat.Png); MemoryStream mergedImageStream = new MemoryStream(); imgBase.Save(mergedImageStream, ImageFormat.Png); mergedImageData = mergedImageStream.ToArray(); mergedImageStream.Close(); } } return mergedImageData; }
这是一个使用Array.CopyTo的简单例子。 我认为它回答你的问题,并给出了一个CopyTo使用的例子 – 当我需要使用这个函数时,我总是感到困惑,因为帮助有点不清楚 – 索引是发生插入的目标数组中的位置。
int[] xSrc1 = new int[3] { 0, 1, 2 }; int[] xSrc2 = new int[5] { 3, 4, 5, 6 , 7 }; int[] xAll = new int[xSrc1.Length + xSrc2.Length]; xSrc1.CopyTo(xAll, 0); xSrc2.CopyTo(xAll, xSrc1.Length);
我想你不能简单得多。
只是要注意一个选项:如果你正在使用的数组是基本types – 布尔(bool),Char,SByte,Byte,Int16(short),UInt16,Int32(int),UInt32,Int64(long ),UInt64,IntPtr,UIntPtr,单或双 – 那么你可以(或应该?)尝试使用Buffer.BlockCopy 。 根据缓冲类的MSDN页面:
这个类比System.Array类中的类似方法提供了更好的操作基本types的性能。
以@ OwenP的答案中的C#2.0为例,它的工作原理如下:
int[] front = { 1, 2, 3, 4 }; int[] back = { 5, 6, 7, 8 }; int[] combined = new int[front.Length + back.Length]; Buffer.BlockCopy(front, 0, combined, 0, front.Length); Buffer.BlockCopy(back, 0, combined, front.Length, back.Length);
Buffer.BlockCopy
和@OwenP使用的Array.Copy
在语法上几乎没有什么区别,但是这应该会更快(即使只是略微)。
我假设你正在使用自己的数组types,而不是内置的.NET数组:
public string[] merge(input1, input2) { string[] output = new string[input1.length + input2.length]; for(int i = 0; i < output.length; i++) { if (i >= input1.length) output[i] = input2[i-input1.length]; else output[i] = input1[i]; } return output; }
另一种方法是使用内build的ArrayList类。
public ArrayList merge(input1, input2) { Arraylist output = new ArrayList(); foreach(string val in input1) output.add(val); foreach(string val in input2) output.add(val); return output; }
这两个例子都是C#。
int [] SouceArray1 = new int[] {2,1,3}; int [] SourceArray2 = new int[] {4,5,6}; int [] targetArray = new int [SouceArray1.Length + SourceArray2.Length]; SouceArray1.CopyTo(targetArray,0); SourceArray2.CopyTo(targetArray,SouceArray1.Length) ; foreach (int i in targetArray) Console.WriteLine(i + " ");
使用上面的代码,两个数组可以很容易地合并。
此代码适用于所有情况:
int[] a1 ={3,4,5,6}; int[] a2 = {4,7,9}; int i = a1.Length-1; int j = a2.Length-1; int resultIndex= i+j+1; Array.Resize(ref a2, a1.Length +a2.Length); while(resultIndex >=0) { if(i != 0 && j !=0) { if(a1[i] > a2[j]) { a2[resultIndex--] = a[i--]; } else { a2[resultIndex--] = a[j--]; } } else if(i>=0 && j<=0) { a2[resultIndex--] = a[i--]; } else if(j>=0 && i <=0) { a2[resultIndex--] = a[j--]; } }
创build和扩展方法来处理null
public static class IEnumerableExtenions { public static IEnumerable<T> UnionIfNotNull<T>(this IEnumerable<T> list1, IEnumerable<T> list2) { if (list1 != null && list2 != null) return list1.Union(list2); else if (list1 != null) return list1; else if (list2 != null) return list2; else return null; } }
尝试这个:
ArrayLIst al = new ArrayList(); al.AddRange(array_1); al.AddRange(array_2); al.AddRange(array_3); array_4 = al.ToArray();