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 }));
--
- - -
Right now I use
现在我使用
int[] z = x.Concat(y).ToArray();
Is there an easier or more efficient method?
有没有更简单或更有效的方法?
21 个解决方案
#1
259
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
#2
67
Try this:
试试这个:
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
#3
43
You could write an extension method:
您可以编写一个扩展方法:
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;
}
Then:
然后:
int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}
#4
33
I settled on a more general-purpose solution that allows concatenating an arbitrary set of one-dimensional arrays of the same type. (I was concatenating 3+ at a time.)
我选择了一种更通用的解决方案,它允许将同一类型的任意一组一维数组连接在一起。(我一次连接了3+。)
My function:
我的函数:
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;
}
And usage:
和用法:
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}
#5
24
This is it:
就是这样:
using System.Linq;
int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };
// Concatenate array1 and array2.
var result1 = array1.Concat(array2);
#6
9
You can take the ToArray() call off the end. Is there a reason you need it to be an array after the call to Concat?
您可以使用ToArray()调用结束。有什么原因你需要它作为一个数组在调用Concat之后?
Calling Concat creates an iterator over both arrays. It does not create a new array so you have not used more memory for a new array. When you call ToArray you actually do create a new array and take up the memory for the new array.
调用Concat在两个数组上创建一个迭代器。它不会创建新的数组,因此您不会为新数组使用更多的内存。当您调用ToArray时,实际上确实创建了一个新的数组,并为新数组占用内存。
So if you just need to easily iterate over both then just call Concat.
因此,如果你只需要简单地迭代,然后调用Concat。
#7
7
I know the OP was only mildly curious about performance. That larger arrays may get a different result (see @kurdishTree). And that it usually does not matter (@jordan.peoples). None the less, I was curious and therefore lost my mind ( as @TigerShark was explaining).... I mean that I wrote a simple test based on the original question.... and all the answers....
我知道OP只是对性能有点好奇。更大的数组可能会得到不同的结果(见@kurdishTree)。而这通常并不重要(@jordan.people)。然而,我很好奇,因此失去了理智(正如@TigerShark所解释的)我的意思是,我写了一个简单的测试基于原始问题....和所有的答案....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace concat
{
class Program
{
static void Main(string[] args)
{
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int itter = 50000;
Console.WriteLine("test iterations: {0}", itter);
DateTime startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
int[] z;
z = x.Concat(y).ToArray();
}
Console.WriteLine ("Concat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
var vz = new int[x.Length + y.Length];
x.CopyTo(vz, 0);
y.CopyTo(vz, x.Length);
}
Console.WriteLine ("CopyTo Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
}
Console.WriteLine("list.AddRange Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.Concat(x, y);
}
Console.WriteLine("Concat(x, y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArrays(x, y);
}
Console.WriteLine("ConcatArrays Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.SSConcat(x, y);
}
Console.WriteLine("SSConcat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int k = 0; k < itter; k++)
{
int[] three = new int[x.Length + y.Length];
int idx = 0;
for (int i = 0; i < x.Length; i++)
three[idx++] = x[i];
for (int j = 0; j < y.Length; j++)
three[idx++] = y[j];
}
Console.WriteLine("Roll your own Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLinq(x, y);
}
Console.WriteLine("ConcatArraysLinq Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLambda(x, y);
}
Console.WriteLine("ConcatArraysLambda Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
List<int> targetList = new List<int>(x);
targetList.Concat(y);
}
Console.WriteLine("targetList.Concat(y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] result = x.ToList().Concat(y.ToList()).ToArray();
}
Console.WriteLine("x.ToList().Concat(y.ToList()).ToArray() Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
}
}
static class Methods
{
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;
}
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;
}
public static T[] SSConcat<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;
}
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();
}
}
}
The result was:
其结果是:
Roll your own wins.
滚你自己的获胜。
#8
5
Be careful with the Concat
method. The post Array Concatenation in C# explains that:
小心使用Concat方法。c#中的post数组连接解释如下:
var z = x.Concat(y).ToArray();
Will be inefficient for large arrays. That means the Concat
method is only for meduim-sized arrays (up to 10000 elements).
对于大型数组来说将是低效的。这意味着Concat方法只适用于meduimsize数组(最多10000个元素)。
#9
4
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;
}
#10
3
More efficient (faster) to use Buffer.BlockCopy
over Array.CopyTo
,
更高效(更快)使用缓冲区。BlockCopy Array.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));
I wrote a simple test program that "warms up the Jitter", compiled in release mode and ran it without a debugger attached, on my machine.
我编写了一个简单的测试程序,在我的机器上,用释放模式编译并在没有调试器的情况下运行它。
For 10,000,000 iterations of the example in the question
在这个问题的例子中有10,000,000次迭代。
Concat took 3088ms
Concat女士花了3088
CopyTo took 1079ms
CopyTo女士花了1079
BlockCopy took 603ms
BlockCopy女士花了603
If I alter the test arrays to two sequences from 0 to 99 then I get results similar to this,
如果我将测试数组从0更改为99,那么我将得到类似的结果,
Concat took 45945ms
Concat女士花了45945
CopyTo took 2230ms
CopyTo女士花了2230
BlockCopy took 1689ms
BlockCopy女士花了1689
From these results I can assert that the CopyTo
and BlockCopy
methods are significantly more efficient than Concat
and furthermore, if performance is a goal, BlockCopy
has value over CopyTo
.
从这些结果中,我可以断言,CopyTo和BlockCopy方法明显比Concat更有效,而且,如果性能是一个目标,那么BlockCopy比CopyTo具有价值。
To caveat this answer, if performance doesn't matter, or there will be few iterations choose the method you find easiest. Buffer.BlockCopy
does offer some utility for type conversion beyond the scope of this question.
要注意这个答案,如果性能不重要,或者会有很少的迭代选择最容易的方法。缓冲区。BlockCopy确实提供了一些用于类型转换的实用工具,超出了这个问题的范围。
#11
3
Late Answer :-).
晚回答:-)。
public static class ArrayExtention
{
public static T[] Concatenate<T>(this T[] array1, T[] array2)
{
T[] result = new T[array1.Length + array2.Length];
array1.CopyTo(result, 0);
array2.CopyTo(result, array1.Length);
return result;
}
}
#12
2
You can do it the way you have referred to, or if you want to get really manual about it you can roll your own loop:
你可以按照你提到的方式来做,或者如果你想获得真正的手册,你可以滚动你自己的循环:
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];
#13
2
The most efficient structure in terms of RAM (and CPU) to hold the combined array would be a special class that implements IEnumerable (or if you wish even derives from Array) and links internally to the original arrays to read the values. AFAIK Concat does just that.
使用RAM(和CPU)来保存组合数组的最有效的结构是一个特殊的类,它实现了IEnumerable(或者,如果你想从数组中获得),并在内部链接到原始数组来读取这些值。AFAIK Concat就是这么做的。
In your sample code you could omit the .ToArray() though, which would make it more efficient.
在您的示例代码中,可以省略. toarray(),这将使它更高效。
#14
1
What you need to remember is that when using LINQ you are utilizing delayed execution. The other methods described here all work perfectly, but they are executed immediately. Furthermore the Concat() function is probably optimized in ways you can't do yourself (calls to internal API's, OS calls etc.). Anyway, unless you really need to try and optimize, you're currently on your path to "the root of all evil" ;)
您需要记住的是,当使用LINQ时,您使用的是延迟执行。这里描述的其他方法都是完美的,但是它们是立即执行的。此外,Concat()函数可能以您自己无法完成的方式进行优化(调用内部API、OS调用等)。不管怎样,除非你真的需要去尝试和优化,否则你就会踏上“万恶之源”的道路。
#15
1
I've found an elegant one line solution using LINQ or Lambda expression, both work the same (LINQ is converted to Lambda when program is compiled). The solution works for any array type and for any number of arrays.
我找到了一个使用LINQ或Lambda表达式的优雅的一行解决方案,两者都是相同的(在编译程序时,LINQ被转换为Lambda)。该解决方案适用于任何数组类型和任意数量的数组。
Using LINQ:
使用LINQ:
public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
return (from array in arrays
from arr in array
select arr).ToArray();
}
Using Lambda:
使用λ:
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
I've provided both for one's preference. Performance wise @Sergey Shteyn's or @deepee1's solutions are a bit faster, Lambda expression being the slowest. Time taken is dependant on type(s) of array elements, but unless there are millions of calls, there is no significant difference between the methods.
我已经提供了两者的偏好。Performance wise @Sergey Shteyn's或@deepee1的解决方案稍微快一点,Lambda表达式是最慢的。时间依赖于数组元素的类型(s),但是除非有数百万个调用,否则方法之间没有显著差异。
#16
1
Try the following:
试试以下:
T[] r1 = new T[size1];
T[] r2 = new T[size2];
List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();
#17
1
Sorry to revive an old thread, but how about this:
很抱歉让旧的线程恢复过来,但是这个怎么样:
static IEnumerable<T> Merge<T>(params T[][] arrays)
{
var merged = arrays.SelectMany(arr => arr);
foreach (var t in merged)
yield return t;
}
Then in your code:
然后在你的代码:
int[] x={1, 2, 3};
int[] y={4, 5, 6};
var z=Merge(x, y); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
Until you call .ToArray()
, .ToList()
, or .ToDictionary(...)
, the memory is not allocated, you are free to "build your query" and either call one of those three to execute it or simply go through them all by using foreach (var i in z){...}
clause which returns an item at a time from the yield return t;
above...
在调用.ToArray()、.ToList()或.ToDictionary(…)之前,没有分配内存,您可以*地“构建查询”,或者调用其中的一个来执行它,或者简单地通过使用foreach(在z中的var i)来遍历它们。}子句,它从收益率返回t时返回一个项;以上……
The above function can be made into an extension as follows:
以上功能可作如下延伸:
static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
var merged = array1.Concat(array2);
foreach (var t in merged)
yield return t;
}
So in the code, you can do something like:
在代码中,你可以这样做:
int[] x1={1, 2, 3};
int[] x2={4, 5, 6};
int[] x3={7, 8};
var z=x1.Merge(x2).Merge(x3); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
The rest is the same as before.
其余的和以前一样。
One other improvement to this would be changing T[]
into IEnumerable<T>
(so the params T[][]
would become params IEnumerable<T>[]
) to make these functions accept more than just arrays.
另一个改进是将T[]改为IEnumerable
Hope this helps.
希望这个有帮助。
#18
0
For int[] what you've done looks good to me. astander's answer would also work well for List<int>
.
你做的事对我来说很好。astander的答案同样适用于List
#19
0
For smaller arrays <10000 elements:
对于较小的数组<10000个元素:
using System.Linq;
int firstArray = {5,4,2};
int secondArray = {3,2,1};
int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();
#20
-1
static class Extensions
{
public static T[] Concat<T>(this T[] array1, params T[] array2)
{
return 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;
}
}
I think the above solution is more general & lighter than the others I saw here. It is more general because it doesn't limit concatenation for only two arrays and is lighter because it doesn't use LINQ nor List.
我认为上面的解决方案比我在这里看到的其他解决方案更全面、更轻。它更一般,因为它不限制只对两个数组的连接,而且更轻,因为它不使用LINQ或List。
Note the solution is concise and the added generality doesn't add significant runtime overhead.
注意,解决方案是简洁的,添加的一般性不会增加显著的运行时开销。
#21
-2
int[] x = new int [] { 1, 2, 3}; int[] y = new int [] { 4, 5 };
int[] x = new int[] {1, 2, 3};int[] y = new int[] {4, 5};
int[] z = x.Union(y).ToArray();
int[]z = x.Union(y).ToArray();
#1
259
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
#2
67
Try this:
试试这个:
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
#3
43
You could write an extension method:
您可以编写一个扩展方法:
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;
}
Then:
然后:
int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}
#4
33
I settled on a more general-purpose solution that allows concatenating an arbitrary set of one-dimensional arrays of the same type. (I was concatenating 3+ at a time.)
我选择了一种更通用的解决方案,它允许将同一类型的任意一组一维数组连接在一起。(我一次连接了3+。)
My function:
我的函数:
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;
}
And usage:
和用法:
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}
#5
24
This is it:
就是这样:
using System.Linq;
int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };
// Concatenate array1 and array2.
var result1 = array1.Concat(array2);
#6
9
You can take the ToArray() call off the end. Is there a reason you need it to be an array after the call to Concat?
您可以使用ToArray()调用结束。有什么原因你需要它作为一个数组在调用Concat之后?
Calling Concat creates an iterator over both arrays. It does not create a new array so you have not used more memory for a new array. When you call ToArray you actually do create a new array and take up the memory for the new array.
调用Concat在两个数组上创建一个迭代器。它不会创建新的数组,因此您不会为新数组使用更多的内存。当您调用ToArray时,实际上确实创建了一个新的数组,并为新数组占用内存。
So if you just need to easily iterate over both then just call Concat.
因此,如果你只需要简单地迭代,然后调用Concat。
#7
7
I know the OP was only mildly curious about performance. That larger arrays may get a different result (see @kurdishTree). And that it usually does not matter (@jordan.peoples). None the less, I was curious and therefore lost my mind ( as @TigerShark was explaining).... I mean that I wrote a simple test based on the original question.... and all the answers....
我知道OP只是对性能有点好奇。更大的数组可能会得到不同的结果(见@kurdishTree)。而这通常并不重要(@jordan.people)。然而,我很好奇,因此失去了理智(正如@TigerShark所解释的)我的意思是,我写了一个简单的测试基于原始问题....和所有的答案....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace concat
{
class Program
{
static void Main(string[] args)
{
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };
int itter = 50000;
Console.WriteLine("test iterations: {0}", itter);
DateTime startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
int[] z;
z = x.Concat(y).ToArray();
}
Console.WriteLine ("Concat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
var vz = new int[x.Length + y.Length];
x.CopyTo(vz, 0);
y.CopyTo(vz, x.Length);
}
Console.WriteLine ("CopyTo Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );
startTest = DateTime.Now;
for(int i = 0; i < itter; i++)
{
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
}
Console.WriteLine("list.AddRange Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.Concat(x, y);
}
Console.WriteLine("Concat(x, y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArrays(x, y);
}
Console.WriteLine("ConcatArrays Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.SSConcat(x, y);
}
Console.WriteLine("SSConcat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int k = 0; k < itter; k++)
{
int[] three = new int[x.Length + y.Length];
int idx = 0;
for (int i = 0; i < x.Length; i++)
three[idx++] = x[i];
for (int j = 0; j < y.Length; j++)
three[idx++] = y[j];
}
Console.WriteLine("Roll your own Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLinq(x, y);
}
Console.WriteLine("ConcatArraysLinq Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] z = Methods.ConcatArraysLambda(x, y);
}
Console.WriteLine("ConcatArraysLambda Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
List<int> targetList = new List<int>(x);
targetList.Concat(y);
}
Console.WriteLine("targetList.Concat(y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
startTest = DateTime.Now;
for (int i = 0; i < itter; i++)
{
int[] result = x.ToList().Concat(y.ToList()).ToArray();
}
Console.WriteLine("x.ToList().Concat(y.ToList()).ToArray() Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
}
}
static class Methods
{
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;
}
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;
}
public static T[] SSConcat<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;
}
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();
}
}
}
The result was:
其结果是:
Roll your own wins.
滚你自己的获胜。
#8
5
Be careful with the Concat
method. The post Array Concatenation in C# explains that:
小心使用Concat方法。c#中的post数组连接解释如下:
var z = x.Concat(y).ToArray();
Will be inefficient for large arrays. That means the Concat
method is only for meduim-sized arrays (up to 10000 elements).
对于大型数组来说将是低效的。这意味着Concat方法只适用于meduimsize数组(最多10000个元素)。
#9
4
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;
}
#10
3
More efficient (faster) to use Buffer.BlockCopy
over Array.CopyTo
,
更高效(更快)使用缓冲区。BlockCopy Array.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));
I wrote a simple test program that "warms up the Jitter", compiled in release mode and ran it without a debugger attached, on my machine.
我编写了一个简单的测试程序,在我的机器上,用释放模式编译并在没有调试器的情况下运行它。
For 10,000,000 iterations of the example in the question
在这个问题的例子中有10,000,000次迭代。
Concat took 3088ms
Concat女士花了3088
CopyTo took 1079ms
CopyTo女士花了1079
BlockCopy took 603ms
BlockCopy女士花了603
If I alter the test arrays to two sequences from 0 to 99 then I get results similar to this,
如果我将测试数组从0更改为99,那么我将得到类似的结果,
Concat took 45945ms
Concat女士花了45945
CopyTo took 2230ms
CopyTo女士花了2230
BlockCopy took 1689ms
BlockCopy女士花了1689
From these results I can assert that the CopyTo
and BlockCopy
methods are significantly more efficient than Concat
and furthermore, if performance is a goal, BlockCopy
has value over CopyTo
.
从这些结果中,我可以断言,CopyTo和BlockCopy方法明显比Concat更有效,而且,如果性能是一个目标,那么BlockCopy比CopyTo具有价值。
To caveat this answer, if performance doesn't matter, or there will be few iterations choose the method you find easiest. Buffer.BlockCopy
does offer some utility for type conversion beyond the scope of this question.
要注意这个答案,如果性能不重要,或者会有很少的迭代选择最容易的方法。缓冲区。BlockCopy确实提供了一些用于类型转换的实用工具,超出了这个问题的范围。
#11
3
Late Answer :-).
晚回答:-)。
public static class ArrayExtention
{
public static T[] Concatenate<T>(this T[] array1, T[] array2)
{
T[] result = new T[array1.Length + array2.Length];
array1.CopyTo(result, 0);
array2.CopyTo(result, array1.Length);
return result;
}
}
#12
2
You can do it the way you have referred to, or if you want to get really manual about it you can roll your own loop:
你可以按照你提到的方式来做,或者如果你想获得真正的手册,你可以滚动你自己的循环:
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];
#13
2
The most efficient structure in terms of RAM (and CPU) to hold the combined array would be a special class that implements IEnumerable (or if you wish even derives from Array) and links internally to the original arrays to read the values. AFAIK Concat does just that.
使用RAM(和CPU)来保存组合数组的最有效的结构是一个特殊的类,它实现了IEnumerable(或者,如果你想从数组中获得),并在内部链接到原始数组来读取这些值。AFAIK Concat就是这么做的。
In your sample code you could omit the .ToArray() though, which would make it more efficient.
在您的示例代码中,可以省略. toarray(),这将使它更高效。
#14
1
What you need to remember is that when using LINQ you are utilizing delayed execution. The other methods described here all work perfectly, but they are executed immediately. Furthermore the Concat() function is probably optimized in ways you can't do yourself (calls to internal API's, OS calls etc.). Anyway, unless you really need to try and optimize, you're currently on your path to "the root of all evil" ;)
您需要记住的是,当使用LINQ时,您使用的是延迟执行。这里描述的其他方法都是完美的,但是它们是立即执行的。此外,Concat()函数可能以您自己无法完成的方式进行优化(调用内部API、OS调用等)。不管怎样,除非你真的需要去尝试和优化,否则你就会踏上“万恶之源”的道路。
#15
1
I've found an elegant one line solution using LINQ or Lambda expression, both work the same (LINQ is converted to Lambda when program is compiled). The solution works for any array type and for any number of arrays.
我找到了一个使用LINQ或Lambda表达式的优雅的一行解决方案,两者都是相同的(在编译程序时,LINQ被转换为Lambda)。该解决方案适用于任何数组类型和任意数量的数组。
Using LINQ:
使用LINQ:
public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
return (from array in arrays
from arr in array
select arr).ToArray();
}
Using Lambda:
使用λ:
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
I've provided both for one's preference. Performance wise @Sergey Shteyn's or @deepee1's solutions are a bit faster, Lambda expression being the slowest. Time taken is dependant on type(s) of array elements, but unless there are millions of calls, there is no significant difference between the methods.
我已经提供了两者的偏好。Performance wise @Sergey Shteyn's或@deepee1的解决方案稍微快一点,Lambda表达式是最慢的。时间依赖于数组元素的类型(s),但是除非有数百万个调用,否则方法之间没有显著差异。
#16
1
Try the following:
试试以下:
T[] r1 = new T[size1];
T[] r2 = new T[size2];
List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();
#17
1
Sorry to revive an old thread, but how about this:
很抱歉让旧的线程恢复过来,但是这个怎么样:
static IEnumerable<T> Merge<T>(params T[][] arrays)
{
var merged = arrays.SelectMany(arr => arr);
foreach (var t in merged)
yield return t;
}
Then in your code:
然后在你的代码:
int[] x={1, 2, 3};
int[] y={4, 5, 6};
var z=Merge(x, y); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
Until you call .ToArray()
, .ToList()
, or .ToDictionary(...)
, the memory is not allocated, you are free to "build your query" and either call one of those three to execute it or simply go through them all by using foreach (var i in z){...}
clause which returns an item at a time from the yield return t;
above...
在调用.ToArray()、.ToList()或.ToDictionary(…)之前,没有分配内存,您可以*地“构建查询”,或者调用其中的一个来执行它,或者简单地通过使用foreach(在z中的var i)来遍历它们。}子句,它从收益率返回t时返回一个项;以上……
The above function can be made into an extension as follows:
以上功能可作如下延伸:
static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
var merged = array1.Concat(array2);
foreach (var t in merged)
yield return t;
}
So in the code, you can do something like:
在代码中,你可以这样做:
int[] x1={1, 2, 3};
int[] x2={4, 5, 6};
int[] x3={7, 8};
var z=x1.Merge(x2).Merge(x3); // 'z' is IEnumerable<T>
var za=z.ToArray(); // 'za' is int[]
The rest is the same as before.
其余的和以前一样。
One other improvement to this would be changing T[]
into IEnumerable<T>
(so the params T[][]
would become params IEnumerable<T>[]
) to make these functions accept more than just arrays.
另一个改进是将T[]改为IEnumerable
Hope this helps.
希望这个有帮助。
#18
0
For int[] what you've done looks good to me. astander's answer would also work well for List<int>
.
你做的事对我来说很好。astander的答案同样适用于List
#19
0
For smaller arrays <10000 elements:
对于较小的数组<10000个元素:
using System.Linq;
int firstArray = {5,4,2};
int secondArray = {3,2,1};
int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();
#20
-1
static class Extensions
{
public static T[] Concat<T>(this T[] array1, params T[] array2)
{
return 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;
}
}
I think the above solution is more general & lighter than the others I saw here. It is more general because it doesn't limit concatenation for only two arrays and is lighter because it doesn't use LINQ nor List.
我认为上面的解决方案比我在这里看到的其他解决方案更全面、更轻。它更一般,因为它不限制只对两个数组的连接,而且更轻,因为它不使用LINQ或List。
Note the solution is concise and the added generality doesn't add significant runtime overhead.
注意,解决方案是简洁的,添加的一般性不会增加显著的运行时开销。
#21
-2
int[] x = new int [] { 1, 2, 3}; int[] y = new int [] { 4, 5 };
int[] x = new int[] {1, 2, 3};int[] y = new int[] {4, 5};
int[] z = x.Union(y).ToArray();
int[]z = x.Union(y).ToArray();