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();
有没有更简单或更有效的方法?
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();
有没有更简单或更有效的方法?
Answers:
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
params
参数。
System.IO.Directory.GetFiles()
返回一个字符串数组。
试试这个:
List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
List<int> list = new List<int>(x);
您可以编写一个扩展方法:
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}
Copy
比CopyTo
什么更快?关心详细吗?
我决定使用一种更通用的解决方案,该解决方案可以连接任意一组相同类型的一维数组。(我一次要串联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}
params T[][]
为this T[][]
使其扩展。
就是这个:
using System.Linq;
int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };
// Concatenate array1 and array2.
var result1 = array1.Concat(array2);
int[] result = array1.ToList().Concat(array2.ToList()).toArray();
我相信您不能直接在阵列上应用Concat
toArray()
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string[]'. An explicit conversion exists (are you missing a cast?)
int[] result = ?
,您将答案的问题隐藏在背后var
,因为您的结果将IEnumerable<int>
不是int[]
。(我不喜欢var
方法返回的原因之一)
.ToArray()
调用,此代码将不会返回实际的数组,因此它也是错误的答案。
我知道OP仅对性能感到好奇。较大的数组可能会得到不同的结果(请参阅@kurdishTree)。而且通常没关系(@ jordan.peoples)。但是,我很好奇,因此失去了理智(正如@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();
}
}
}
结果是:
赢得自己的胜利。
CopyTo
将是最快的,并且比快约3倍Roll your own
。
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;
}
更高效的(快)使用Buffer.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));
我编写了一个简单的测试程序,该程序“预热了抖动”,在发布模式下进行了编译,并在未连接调试器的情况下在计算机上运行了该程序。
对于问题中的示例的10,000,000次迭代
Concat花了3088毫秒
CopyTo花了1079ms
BlockCopy花了603ms
如果我将测试数组更改为从0到99的两个序列,那么我得到的结果与此类似,
Concat花了45945毫秒
CopyTo花了2230ms
BlockCopy花了1689毫秒
从这些结果中,我可以断言CopyTo
和BlockCopy
方法比效率要高得多Concat
,此外,如果以性能为目标,BlockCopy
则价值超过CopyTo
。
为了解决这个问题,如果性能无关紧要,或者迭代次数很少,请选择最简单的方法。Buffer.BlockCopy
确实提供了一些超出此问题范围的实用程序来进行类型转换。
很抱歉,无法恢复旧线程,但是如何处理:
static IEnumerable<T> Merge<T>(params T[][] arrays)
{
var merged = arrays.SelectMany(arr => arr);
foreach (var t in merged)
yield return t;
}
然后在您的代码中:
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[]
直到你打电话.ToArray()
,.ToList()
或者.ToDictionary(...)
,内存不分配,你可以自由地“构建查询”和这三任调用一个执行,或干脆通过他们都通过foreach (var i in z){...}
其在从一个时间返回项条款yield return t;
以上...
可以将上述功能扩展为以下功能:
static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
var merged = array1.Concat(array2);
foreach (var t in merged)
yield return t;
}
因此,在代码中,您可以执行以下操作:
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[]
其余与以前相同。
对此的另一种改进是更改T[]
为IEnumerable<T>
(使params T[][]
成为params IEnumerable<T>[]
),以使这些函数接受的不仅仅是数组。
希望这可以帮助。
您可以按照引用的方式进行操作,或者,如果您想真正地手动使用它,可以滚动自己的循环:
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];
我发现使用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();
}
使用Lambda:
public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}
我已根据个人喜好提供了两者。在性能方面,@ Sergey Shteyn或@ deepee1的解决方案速度更快,Lambda表达式的速度最慢。花费的时间取决于数组元素的类型,但是除非有数百万个调用,否则这两种方法之间没有显着差异。
尝试以下方法:
T[] r1 = new T[size1];
T[] r2 = new T[size2];
List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();
这是我的答案:
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
将抵消这种优势,因为它实际上将创建一个新的数组并占用内存。新数组。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();
尽管后一种方法要优雅得多,但前一种方法绝对可以提高性能。
有关更多信息,请参阅这篇文章在我的博客。
对于int [],您所做的工作对我来说看起来不错。旁听者的答案也适用于List<int>
。
对于小于10000个元素的较小数组:
using System.Linq;
int firstArray = {5,4,2};
int secondArray = {3,2,1};
int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();
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 [] x = new int [] {1,2,3}; int [] y =新的int [] {4,5};
int [] z = x.Union(y).ToArray();
Union
这不是一个很好的方法,因为它隐式调用Distinct
并从联接的集合中删除所有重复项。Concat
更好,但这已经在最初的问题中了。
int[] scores = { 100, 90, 90, 80, 75, 60 };
int[] alice = { 50, 65, 77, 90, 102 };
int[] scoreBoard = new int[scores.Length + alice.Length];
int j = 0;
for (int i=0;i<(scores.Length+alice.Length);i++) // to combine two arrays
{
if(i<scores.Length)
{
scoreBoard[i] = scores[i];
}
else
{
scoreBoard[i] = alice[j];
j = j + 1;
}
}
for (int l = 0; l < (scores.Length + alice.Length); l++)
{
Console.WriteLine(scoreBoard[l]);
}