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();
더 쉽고 효율적인 방법이 있습니까?
답변:
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
니까? 정교하게 관리?
나는 동일한 유형의 임의의 1 차원 배열 세트를 연결할 수있는보다 범용적인 솔루션에 정착했습니다. (한 번에 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
보다 작지 않은 경우 (1000 요소와 같이) 가장 빠르며 ~ 3 배 빠릅니다 Roll your own
.
Concat
방법에 주의하십시오 . C # 의 Post Array Concatenation은 다음과 같이 설명합니다.
var z = x.Concat(y).ToArray();
큰 배열에는 비효율적입니다. 즉,이 Concat
방법은 meduim 크기의 배열에만 적용됩니다 (최대 10000 개의 요소).
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은 3088ms 걸렸다
CopyTo는 1079ms 걸렸습니다
BlockCopy 소요 603ms
테스트 배열을 0에서 99의 두 시퀀스로 변경하면 다음과 비슷한 결과가 나타납니다.
Concat은 45945ms 걸렸다
CopyTo는 2230ms 걸렸습니다
BlockCopy는 1689ms 걸렸습니다
이러한 결과를 바탕으로 CopyTo
and 및 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();
후자의 방법은 훨씬 더 우아하지만 전자의 방법은 성능면에서 훨씬 좋습니다.
자세한 내용은 이 게시물을 참조하십시오 은 내 블로그 을 .
더 작은 배열 <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 = 새로운 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]);
}