.NET 2.0中是否有内置函数可以将两个数组合并为一个数组?
阵列属于同一类型。我从我的代码库中广泛使用的函数中获取这些数组,并且无法修改函数以返回不同格式的数据。
我希望尽可能避免编写自己的函数来完成此任务。
答案 0 :(得分:400)
在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可能是最好的解决方案:
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
版本。
答案 1 :(得分:105)
如果您可以操作其中一个阵列,则可以在执行复制之前调整其大小:
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);
否则,您可以创建一个新数组
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);
答案 2 :(得分:53)
使用LINQ:
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Union(arr2).ToArray();
请注意,这将删除重复项。如果要保留重复项,请使用Concat。
答案 3 :(得分:29)
如果您不想删除重复项,请尝试使用
使用LINQ:
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Concat(arr2).ToArray();
答案 4 :(得分:10)
首先,请务必问自己“我真的应该在这里使用数组”这个问题吗?
除非你正在构建一个速度至关重要的东西,否则类似的列表,如List<int>
可能是要走的路。我通过网络发送内容时,唯一使用数组的是字节数组。除此之外,我从不接触它们。
答案 5 :(得分:8)
更容易使用LINQ:
var array = new string[] { "test" }.ToList();
var array1 = new string[] { "test" }.ToList();
array.AddRange(array1);
var result = array.ToArray();
首先将数组转换为列表并合并它们......之后只需将列表转换回数组:)
答案 6 :(得分:7)
我认为您可以使用Array.Copy。它需要一个源索引和目标索引,因此您应该能够将一个数组附加到另一个数组。如果你需要更复杂而不仅仅是将它们附加到另一个,那么这可能不适合你。
答案 7 :(得分:5)
假设目标阵列有足够的空间,Array.Copy()
将起作用。您也可以尝试使用List<T>
及其.AddRange()
方法。
答案 8 :(得分:4)
就个人而言,我更喜欢自己的语言扩展,我可以随意添加或删除它以进行快速原型设计。
以下是字符串的示例。
//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
类型包装器,它存储传递数组的引用/指针,并允许循环整个集合,就好像它是一个普通的数组。 (在HPC,图形处理,图形渲染中很有用......)
您的代码:
var someStringArray = new[]{"a", "b", "c"};
var someStringArray2 = new[]{"d", "e", "f"};
someStringArray.Append(someStringArray2 ); //contains a,b,c,d,e,f
有关整个代码和泛型版本,请参阅:https://gist.github.com/lsauer/7919764
注意:这将返回未扩展的IEnumerable对象。返回扩展对象有点慢。
我从2002年开始编译这样的扩展,在CodeProject和'Stackoverflow'上有很多学分给有用的人。我将很快发布这些内容并将链接放在这里。
答案 9 :(得分:4)
每个人都已经有了发言权,但我认为这比“使用扩展方法”方法更具可读性:
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = Queryable.Concat(arr1, arr2).ToArray();
但它只能在将2个阵列放在一起时使用。
答案 10 :(得分:2)
如果其他人正在寻找如何合并两个图像字节数组:
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;
}
答案 11 :(得分:2)
只是将它作为一个选项注明:如果您正在使用的数组是原始类型 - 布尔值(bool),Char,SByte,Byte,Int16(短),UInt16,Int32(int),UInt32, Int64(长),UInt64,IntPtr,UIntPtr,单或双 - 然后你可以(或应该?)尝试使用Buffer.BlockCopy。根据{{3}}类的MSDN页面:
与Buffer类中的类似方法相比,此类为操作基元类型提供了更好的性能。
使用@ OwenP的System.Array中的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);
{@ 1}}和@OwenP使用的Buffer.BlockCopy
之间的语法几乎没有任何区别,但这应该更快(即使只是略微)。
答案 12 :(得分:1)
这是一个使用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);
我想你不能简单得多。
答案 13 :(得分:1)
我需要一个解决方案来组合未知数量的数组。
感到惊讶的是,没有其他人使用SelectMany
params
提供解决方案。
private static T[] Combine<T>(params IEnumerable<T>[] items) =>
items.SelectMany(i => i).Distinct().ToArray();
如果您不想要不同的项目,请删除不同的内容。
public string[] Reds = new [] { "Red", "Crimson", "TrafficLightRed" };
public string[] Greens = new [] { "Green", "LimeGreen" };
public string[] Blues = new [] { "Blue", "SkyBlue", "Navy" };
public string[] Colors = Combine(Reds, Greens, Blues);
注意:使用distinct时无法保证订购。
答案 14 :(得分:1)
这是我想出的。适用于可变数量的数组。
public static T[] ConcatArrays<T>(params T[][] args)
{
if (args == null)
throw new ArgumentNullException();
var offset = 0;
var newLength = args.Sum(arr => arr.Length);
var newArray = new T[newLength];
foreach (var arr in args)
{
Buffer.BlockCopy(arr, 0, newArray, offset, arr.Length);
offset += arr.Length;
}
return newArray;
}
...
var header = new byte[] { 0, 1, 2};
var data = new byte[] { 3, 4, 5, 6 };
var checksum = new byte[] {7, 0};
var newArray = ConcatArrays(header, data, checksum);
//output byte[9] { 0, 1, 2, 3, 4, 5, 6, 7, 0 }
答案 15 :(得分:0)
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 + " ");
使用上面的代码可以很容易地合并两个Arrays。
答案 16 :(得分:0)
我假设你使用自己的数组类型而不是内置的.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;
}
另一种方法是使用内置的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#。
答案 17 :(得分:0)
创建和扩展方法以处理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;
}
}
答案 18 :(得分:0)
如果源数组本身包含在数组中,则可以使用SelectMany:
var arrays = new[]{new[]{1, 2, 3}, new[]{4, 5, 6}};
var combined = arrays.SelectMany(a => a).ToArray();
foreach (var v in combined) Console.WriteLine(v);
给予
1
2
3
4
5
6
这可能不是最快的方法,但可能取决于用例。
答案 19 :(得分:0)
连接多个数组的简单代码:
string[] arr1 = ...
string[] arr2 = ...
string[] arr3 = ...
List<string> arr = new List<string>(arr1.Length + arr2.Length + arr3.Length);
arr.AddRange(arr1);
arr.AddRange(arr2);
arr.AddRange(arr3);
string[] result = arr.ToArray();
答案 20 :(得分:-1)
这是另一种方法:)
public static void ArrayPush<T>(ref T[] table, object value)
{
Array.Resize(ref table, table.Length + 1); // Resizing the array for the cloned length (+-) (+1)
table.SetValue(value, table.Length - 1); // Setting the value for the new element
}
public static void MergeArrays<T>(ref T[] tableOne, T[] tableTwo) {
foreach(var element in tableTwo) {
ArrayPush(ref tableOne, element);
}
}
答案 21 :(得分:-2)
试试这个:
ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
答案 22 :(得分:-2)
此代码适用于所有情况:
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--];
}
}