source

C#에서 두 어레이를 연결하려면 어떻게 해야 합니까?

ittop 2023. 5. 7. 11:52
반응형

C#에서 두 어레이를 연결하려면 어떻게 해야 합니까?

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개 요소)에만 사용됩니다.

var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);

사용해 보십시오.

List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();

확장 방법을 작성할 수 있습니다.

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}

다음과 같습니다.

using System.Linq;

int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };

// Concatenate array1 and array2.
int[] result1 = array1.Concat(array2).ToArray();

저는 같은 유형의 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}

OP가 공연에 대해 약간의 호기심만 가지고 있었다는 것을 알고 있습니다.더 큰 어레이는 다른 결과를 얻을 수 있습니다(@kurdishTree 참조).그리고 그것은 보통 중요하지 않다는 것 (@jordan).국민)그럼에도 불구하고, 저는 호기심이 생겨서 정신을 잃었습니다 (@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();
        }
    }

}

결과는 다음과 같습니다.

여기에 이미지 설명 입력

자신의 승리를 거두세요.

보다 효율적으로(더 빠르게) 사용할 수 있습니다.

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를 소요했습니다.

복사하는 데 1079ms가 걸렸습니다.

블록 복사에 603ms 소요

테스트 배열을 0에서 99 사이의 두 시퀀스로 변경하면 이와 유사한 결과를 얻을 수 있습니다.

Concat에는 45945ms가 소요되었습니다.

복사하는 데 2230ms가 걸렸습니다.

블록 복사에 1689ms 소요

이러한 결과로부터 나는 주장할 수 있습니다.CopyTo그리고.BlockCopy는 메소드보다 입니다.Concat 더 목표라면, 가성과목면, 가표라만약게다,▁and만목면,,BlockCopy보다 가치가 있습니다.CopyTo.

성능이 중요하지 않거나 반복이 거의 없을 경우 가장 쉬운 방법을 선택하면 이 대답에 주의할 수 있습니다. Buffer.BlockCopy는 이 질문의 범위를 벗어나 형식 변환에 대한 몇 가지 유용성을 제공합니다.

ToArray() 호출을 끝에서 해제할 수 있습니다.Concat에 전화한 후에 어레이가 되어야 하는 이유가 있습니까?

Concat을 호출하면 두 배열 모두에 반복기가 생성됩니다.새 배열을 만들지 않으므로 새 배열에 더 많은 메모리를 사용하지 않았습니다.ToArray를 호출하면 실제로 새 어레이를 생성하고 새 어레이의 메모리를 차지하게 됩니다.

따라서 두 가지 모두를 쉽게 반복해야 한다면 콩캣에 전화하십시오.

늦은 답변 :-).

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;
        }

    }

제 대답은 이렇습니다.

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();

비록 후자의 방법이 훨씬 더 우아하지만, 성능 면에서는 확실히 전자의 방법이 더 좋습니다.

자세한 내용은 제 블로그에 있는 이 게시물을 참조하시기 바랍니다.

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;
}

결합된 어레이를 유지하는 RAM(및 CPU) 측면에서 가장 효율적인 구조는 IEnumberable(또는 어레이에서 파생되기를 원하는 경우)을 구현하고 값을 읽기 위해 원래 어레이에 내부적으로 연결하는 특수 클래스입니다.AFAIK Concat은 바로 그것을 합니다.

샘플 코드에서 를 생략할 수 있습니다.어레이()에 연결하면 효율성이 향상됩니다.

오래된 스레드를 되살려서 죄송합니다만, 이것은 어떻습니까?

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>[]를 사용하여 이러한 할 수 있습니다.를 사용하여 이러한 기능을 단순한 배열 이상으로 수용할 수 있습니다.

이게 도움이 되길 바랍니다.

LINQ 또는 람다 식을 사용하는 우아한 한 줄 솔루션을 찾았습니다. 둘 다 동일하게 작동합니다(LINQ는 프로그램이 컴파일되면 람다로 변환됩니다).이 솔루션은 모든 어레이 유형 및 어레이 수에 관계없이 작동합니다.

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 또는 @deepe1의 솔루션은 약간 더 빠르며 람다 식은 가장 느립니다.소요되는 시간은 배열 요소의 유형에 따라 다르지만 수백만 개의 호출이 없는 한 메서드 간에 큰 차이가 없습니다.

참조한 방법으로 이 작업을 수행하거나 수동으로 작업을 수행하려면 직접 루프를 굴릴 수 있습니다.

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를 사용할 때 지연 실행을 사용한다는 것입니다.여기에 설명된 다른 방법은 모두 완벽하게 작동하지만 즉시 실행됩니다.또한 Concat() 기능은 사용자가 직접 할 수 없는 방식(내부 API 호출, OS 호출 등)으로 최적화되어 있을 수 있습니다.어쨌든, 당신이 정말로 노력하고 최적화할 필요가 없는 한, 당신은 현재 "모든 악의 근원"으로 가는 길에 있습니다;)

다음을 시도합니다.

T[] r1 = new T[size1];
T[] r2 = new T[size2];

List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();

당신이 한 일은 제가 보기에 좋습니다. 스탠더의 대답도 좋습니다.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나 목록을 사용하지 않기 때문에 더 일반적입니다.

솔루션은 간결하고 일반성이 추가되어 런타임 오버헤드가 크게 증가하지 않습니다.

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]);
}

저는 목록이 이 목적에 적합할 것이라고 생각합니다.

다음과 같은 목록을 만들 수 있습니다.

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

그런 다음 루프마다 를 사용하여 원하는 수의 어레이를 반복하고 목록에 추가하기만 하면 됩니다.

foreach (int i in nameOfArray)
{
    Items.Add(i); 
}

목록을 사용하면 범위 외 예외 문제가 제거됩니다.목록은 배열과 동일한 기능에 모두 사용할 수 있습니다.유일한 의미 있는 차이점은 항목 수에 대한 엄격한 제한이 없다는 것입니다.

varz = x.콘카트(y).대상 배열();

언급URL : https://stackoverflow.com/questions/1547252/how-do-i-concatenate-two-arrays-in-c

반응형