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个元素)。
我选择了一种更通用的解决方案,它允许连接同一类型的一维数组的任意集。(我一次连接了3个+。)
我的函数:
public static T[] ConcatArrays<T>(params T[][] list)
{
var result = new T[list.Sum(a => a.Length)];
int offset = 0;
for (int x = 0; x < list.Length; x++)
{
list[x].CopyTo(result, offset);
offset += list[x].Length;
}
return result;
}
和用法:
int[] a = new int[] { 1, 2, 3 };
int[] b = new int[] { 4, 5, 6 };
int[] c = new int[] { 7, 8 };
var y = ConcatArrays(a, b, c); //Results in int[] {1,2,3,4,5,6,7,8}
我发现了一个优雅的一行解决方案,使用LINQ或Lambda表达式,两者工作相同(当程序编译时LINQ转换为Lambda)。该解决方案适用于任何数组类型和任何数量的数组。
使用LINQ:
public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
return (from array in arrays
from arr in array
select arr).ToArray();
}
使用λ:
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
这两种我都提供了。性能方面@Sergey Shteyn的或@deepee1的解决方案更快一些,Lambda表达式是最慢的。所花费的时间取决于数组元素的类型,但除非有数百万次调用,否则方法之间没有显著差异。
public static T[] Concat<T>(this T[] first, params T[][] arrays)
{
int length = first.Length;
foreach (T[] array in arrays)
{
length += array.Length;
}
T[] result = new T[length];
length = first.Length;
Array.Copy(first, 0, result, 0, first.Length);
foreach (T[] array in arrays)
{
Array.Copy(array, 0, result, length, array.Length);
length += array.Length;
}
return result;
}
static class Extensions
{
public static T[] Concat<T>(this T[] array1, params T[] array2) => ConcatArray(array1, array2);
public static T[] ConcatArray<T>(params T[][] arrays)
{
int l, i;
for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++);
var a = new T[l];
for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++)
arrays[i].CopyTo(a, l);
return a;
}
}
我认为上面的解决方案比我在这里看到的其他解决方案更普遍和更轻。它更通用,因为它不限制只对两个数组进行连接,也更轻便,因为它不使用LINQ和List。
注意,这个解决方案很简洁,并且添加的通用性不会增加大量的运行时开销。
以下是我的回答:
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();
虽然后一种方法要优雅得多,但前一种方法的性能肯定更好。
更多信息,请参考我博客上的这篇文章。