关于C#:在.NET中合并两个数组

关于C#:在.NET中合并两个数组

Merging two arrays in .NET

.NET 2.0中是否有内置函数将两个数组合并为一个数组?

数组都是相同的类型。 我是从代码库中广泛使用的函数获取这些数组的,无法修改该函数以其他格式返回数据。

我希望避免编写自己的函数来完成此操作(如果可能)。


在C#3.0中,可以使用LINQ的Concat方法轻松完成此操作:

1
2
3
int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = front.Concat(back).ToArray();

在C#2.0中,您没有直接的方法,但是Array.Copy可能是最好的解决方案:

1
2
3
4
5
6
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
2
3
4
5
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);

否则,您可以制作一个新数组

1
2
3
4
5
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上可用数组方法的更多信息。


使用LINQ:

1
2
3
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Union(arr2).ToArray();

请记住,这将删除重复项。如果要保留重复项,请使用Concat。


如果您不想删除重复项,请尝试此操作

使用LINQ:

1
2
3
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Concat(arr2).ToArray();


首先,请确保您问自己一个问题:"我真的应该在这里使用数组吗?"?

除非您要构建对速度至关重要的东西,否则使用List之类的类型化List可能是可行的方法。通过网络发送内容时,我唯一一次使用数组是用于字节数组。除此之外,我从未碰过它们。


使用LINQ更容易:

1
2
3
4
var array = new string[] {"test" }.ToList();
var array1 = new string[] {"test" }.ToList();
array.AddRange(array1);
var result = array.ToArray();

首先将数组转换为列表并将其合并...之后,只需将列表转换回数组即可:)


我认为您可以为此使用Array.Copy。它需要一个源索引和一个目标索引,因此您应该能够将一个数组附加到另??一个数组。如果您需要的不只是将一个附加到另一个上而变得更加复杂,那么这可能不是适合您的工具。


假设目标数组有足够的空间,Array.Copy()将起作用。您也可以尝试使用List< T >及其.AddRange()方法。


就个人而言,我更喜欢自己的语言扩展,可以随意添加或删除这些语言扩展以快速进行原型制作。

以下是字符串的示例。

1
2
3
4
5
6
7
8
9
10
11
12
//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,图形处理,图形渲染中很有用...)

您的代码:

1
2
3
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"上的有用人员。我将在短期内发布这些链接,并将链接放在此处。


每个人都已经发表了意见,但是我认为这比"用作扩展方法"方法更具可读性:

1
2
3
var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = Queryable.Concat(arr1, arr2).ToArray();

但是,只能在将2个数组放在一起时使用。


这就是我想出的。 适用于可变数量的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
    }

...

1
2
3
4
5
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 }

如果其他人正在寻找如何合并两个图像字节数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        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.webp"), ImageFormat.Png);
                    MemoryStream mergedImageStream = new MemoryStream();
                    imgBase.Save(mergedImageStream, ImageFormat.Png);
                    mergedImageData = mergedImageStream.ToArray();
                    mergedImageStream.Close();
                }
            }
            return mergedImageData;
        }

只是将其记录为一个选项:如果您使用的数组是基本类型Boolean(布尔型),Char,SByte,Byte,Int16(短型),UInt16,Int32(int),UInt32,Int64(长型) ,UInt64,IntPtr,UIntPtr,Single或Double,则可以(或应该?)尝试使用Buffer.BlockCopy。根据Buffer类的MSDN页面:

This class provides better performance for manipulating primitive types than similar methods in the System.Array class.

以@OwenP的答案中的C#2.0示例作为起点,它的工作方式如下:

1
2
3
4
5
6
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);

@xOwenP使用的Buffer.BlockCopyArray.Copy在语法上几乎没有任何区别,但这应该更快(即使只是一点点)。


这是一个使用Array.CopyTo的简单示例。
我认为它回答了您的问题,并提供了一个CopyTo用法的示例-当我需要使用此函数时,我总是很困惑,因为帮助有点不清楚-索引是目标数组在其中发生插入的位置。

1
2
3
4
5
6
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);

我想你再简单不过了。


我需要一个解决方案来组合数量未知的数组。

惊讶的是没有其他人提供使用SelectManyparams的解决方案。

1
2
 private static T[] Combine< T >(params IEnumerable< T >[] items) =>
                    items.SelectMany(i => i).Distinct().ToArray();

如果您不希望使用不重复项,则只需删除不重复项即可。

1
2
3
4
5
 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时,绝对不能保证订购。


创建和扩展方法来处理null

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
    }
}

我假设您使用的是自己的数组类型,而不是内置的.NET数组:

1
2
3
4
5
6
7
8
9
10
11
12
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类。

1
2
3
4
5
6
7
8
9
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#。


1
2
3
4
5
6
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 +"");

使用上面的代码,可以很容易地合并两个数组。


此代码适用于所有情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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--];
    }
}


尝试这个:

1
2
3
4
5
ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();


推荐阅读

    excel怎么用乘法函数

    excel怎么用乘法函数,乘法,函数,哪个,excel乘法函数怎么用?1、首先用鼠标选中要计算的单元格。2、然后选中单元格后点击左上方工具栏的fx公

    wps如何合并章节

    wps如何合并章节,WPS教程,1.WPS表格如何实现单元格合并?WPS 表格在新版本中增加了“合并单元格”系列按钮,同时配有下拉菜单和快捷键。新增

    excel中乘法函数是什么?

    excel中乘法函数是什么?,乘法,函数,什么,打开表格,在C1单元格中输入“=A1*B1”乘法公式。以此类推到多个单元。1、A1*B1=C1的Excel乘法公式

    标准差excel用什么函数?

    标准差excel用什么函数?,函数,标准,什么,在数据单元格的下方输入l标准差公式函数公式“=STDEVPA(C2:C6)”。按下回车,求出标准公差值。详细

    公共CPU接口类型的详细描述

    公共CPU接口类型的详细描述,,我们知道CPU是电脑的大脑, CPU的处理速度直接决定电脑的性能, 那你知道CPU发展到现在, 都那些CPU接口类型吗.

    针灸科设置|针灸科常见操作

    针灸科设置|针灸科常见操作,,1. 针灸科常见操作⒈临床实践技能(临床实际本领)考核 ⑴基本操作:①中医四诊、针灸、推拿、拔罐等中医临床技术;

    如何解决errtor加载操作系统的引导

    如何解决errtor加载操作系统的引导,,电脑启动后,屏幕上出现了errtor加载操作system错误提示,无法继续启动进入系统。以下是diskedit软件解决

    萤石设置方法|萤石操作手册下载

    萤石设置方法|萤石操作手册下载,,1. 萤石操作手册下载寻找验证码方法:恢复萤石云的验证码,需要在浏览器输入摄像头的ip地址登陆到一下界面:此