int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = // your answer here...

Debug.Assert(z.SequenceEqual(new int[] { 1, 2, 3, 4, 5 }));

现在我用

int[] z = x.Concat(y).ToArray();

有没有更简单或更有效的方法?


使用Concat方法时要小心。c#中的数组拼接这篇文章解释了:

var z = x.Concat(y).ToArray();

对于大型阵列来说效率很低。这意味着Concat方法仅适用于中型数组(最多10000个元素)。


当前回答

以下是我的回答:

int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

此方法可用于初始化级别,例如定义静态数组的静态连接:

public static int[] a = new int [] { 1, 2, 3, 4, 5 };
public static int[] b = new int [] { 6, 7, 8 };
public static int[] c = new int [] { 9, 10 };

public static int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

但是,你需要注意两点:

Concat方法在两个数组上创建迭代器:它不创建新数组,因此在内存使用方面很有效:然而,随后的ToArray将抵消这种优势,因为它实际上创建了一个新数组,并为新数组占用内存。 正如@Jodrell所说,Concat对于大型数组来说效率相当低:它应该只用于中型数组。

如果必须以性能为目标,可以使用以下方法:

/// <summary>
/// Concatenates two or more arrays into a single one.
/// </summary>
public static T[] Concat<T>(params T[][] arrays)
{
    // return (from array in arrays from arr in array select arr).ToArray();

    var result = new T[arrays.Sum(a => a.Length)];
    int offset = 0;
    for (int x = 0; x < arrays.Length; x++)
    {
        arrays[x].CopyTo(result, offset);
        offset += arrays[x].Length;
    }
    return result;
}

或者(对于喜欢说俏皮话的人):

int[] z = (from arrays in new[] { a, b, c } from arr in arrays select arr).ToArray();

虽然后一种方法要优雅得多,但前一种方法的性能肯定更好。

更多信息,请参考我博客上的这篇文章。

其他回答

使用Buffer更有效(更快)。对数组进行BlockCopy。CopyTo,

int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = new int[x.Length + y.Length];
var byteIndex = x.Length * sizeof(int);
Buffer.BlockCopy(x, 0, z, 0, byteIndex);
Buffer.BlockCopy(y, 0, z, byteIndex, y.Length * sizeof(int));

我写了一个简单的测试程序来“加热Jitter”,在发布模式下编译,并在没有调试器的情况下在我的机器上运行。

对于问题中例子的10,000,000次迭代

Concat花了3088ms CopyTo耗时1079ms BlockCopy耗时603毫秒

如果我将测试数组改变为从0到99的两个序列,那么我会得到类似于这样的结果,

Concat花了45945ms CopyTo花了2230ms BlockCopy耗时1689ms

从这些结果中,我可以断言CopyTo和BlockCopy方法明显比Concat更有效,此外,如果性能是一个目标,BlockCopy比CopyTo更有价值。

要注意这个答案,如果性能不重要,或者迭代很少,请选择您认为最简单的方法。缓冲区。BlockCopy确实提供了一些超出这个问题范围的类型转换实用程序。

你可以按照你提到的方式来做,或者如果你想要真正的手动操作,你可以滚动你自己的循环:

string[] one = new string[] { "a", "b" };
string[] two = new string[] { "c", "d" };
string[] three;

three = new string[one.Length + two.Length];

int idx = 0;

for (int i = 0; i < one.Length; i++)
    three[idx++] = one[i];
for (int j = 0; j < two.Length; j++)
    three[idx++] = two[j];

在我看来,你所做的一切还不错。astander的答案也适用于List<int>。

我认为列出一份清单很适合这个目的。

你可以创建一个这样的列表。

List<int> Items = new List<int>();  

然后你可以很容易地使用for每个循环遍历任意数量的数组并将它们添加到列表中。

foreach (nameOfArray中的int i) { Items.Add(我); }

如果使用列表,则可以消除出界异常的问题。列表可以用于与数组相同的所有功能。唯一有意义的区别是缺少项目数量的硬性限制。

你可以写一个扩展方法:

public static T[] Concat<T>(this T[] x, T[] y)
{
    if (x == null) throw new ArgumentNullException("x");
    if (y == null) throw new ArgumentNullException("y");
    int oldLen = x.Length;
    Array.Resize<T>(ref x, x.Length + y.Length);
    Array.Copy(y, 0, x, oldLen, y.Length);
    return x;
}

然后:

int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}