Làm cách nào để ghép hai mảng trong C #?


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

Ngay bây giờ tôi sử dụng

int[] z = x.Concat(y).ToArray();

Có một phương pháp dễ dàng hơn hoặc hiệu quả hơn?


8
Bạn có ý nghĩa gì bởi "hiệu quả"? Mã này đủ ngắn, vì vậy tôi cho rằng bạn có nghĩa là hiệu quả về mặt CPU / RAM?
TToni

4
Không, một cái nhìn nhanh với Reflector cho thấy rằng nó sử dụng bộ đệm gấp đôi khi đầy
erikkallen

Chỉ cần rõ ràng tôi cần z là một kiểu int [].
hwiechers

4
Tôi không thực sự quan tâm đến hiệu quả. (Tôi đã nói dễ dàng hơn hoặc hiệu quả hơn.) Tôi đã đặt câu hỏi để kiểm tra xem những người khác đang xử lý công việc chung này như thế nào.
hwiechers

Câu trả lời:


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

8
@manthrax -> Để bảo vệ, C # có xu hướng ủng hộ các danh sách mạnh hơn nhiều so với mảng. Có vẻ như mục đích chức năng duy nhất để sử dụng mảng là cho các cuộc gọi Interop (Unmanaged C ++).
Levi Fuller

@LeviFuller Một nơi khác mà C # sử dụng mảng là với các paramstham số số biến.
ChrisW

1
@LeviFuller - thật kỳ lạ khi nhiều hệ thống thường xuyên trả về mảng thay vì danh sách. ví dụ System.IO.Directory.GetFiles()trả về một chuỗi các chuỗi.
orion elenzil

4
Đây không phải là số lẻ. Một mảng là bất biến, một danh sách không. Ngoài ra, một Danh sách sử dụng nhiều bộ nhớ hơn một mảng, trừ khi TrimExcess được gọi (điều này không xảy ra trong ToList)
CSharpie

1
Ngoài ra mảng nhanh hơn danh sách khi truy cập dữ liệu, vì danh sách chỉ bao bọc mảng bên trong và có phí để gọi bộ chỉ mục.
C0DEF52

84

Thử cái này:

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

5
Hoặc thậm chíList<int> list = new List<int>(x);
Matthew Scharley

7
Làm thế nào là hiệu quả hơn x.Concat (y)? Nó hoạt động và tất cả, tôi chỉ tự hỏi nếu có một cái gì đó làm cho nó tốt hơn?
Mike Hai

7
bạn có thể muốn tạo Danh sách dòng đầu tiên <int> list = Danh sách mới <int> (x.Lạng + y.Lạng); Để tránh thay đổi kích thước có thể xảy ra khi bạn gọi AddRange
Mike Two

5
@Mathew Scharley. Câu hỏi là yêu cầu một giải pháp hiệu quả hơn. Tôi biết tiêu đề làm cho nó có vẻ như bất kỳ sự kết hợp cũ nào sẽ làm nhưng câu hỏi đầy đủ vượt xa điều đó. Đọc một số câu trả lời tôi chỉ cảm thấy một số người đang trả lời tiêu đề. Vì vậy, tôi nghĩ rằng câu trả lời này có lẽ nên đề cập đến hiệu quả nếu nó xứng đáng nhận được sự ủng hộ vì đó dường như là điểm của câu hỏi.
Mike Hai

2
Hóa ra AddRange thực sự là một quá trình khá tốn kém, vì vậy câu trả lời đầu tiên trên diễn đàn này nên là cách tiếp cận được ưa thích: dotnetperls.com/insertrange
Liam

49

Bạn có thể viết một phương thức mở rộng:

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

Sau đó:

int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}

1
Không phải đã có một phương thức mở rộng hoạt động trên bất kỳ IEnumerable nào?
Mike Hai

2
Có, và tôi sẽ sử dụng nó một cách vui vẻ cho hầu hết các trường hợp. Nhưng họ có rất nhiều chi phí. Nó phụ thuộc; 98% thời gian các chi phí là tốt. Tuy nhiên, nếu bạn ở trong 2%, thì một số công việc ghi nhớ / mảng trực tiếp là tiện dụng.
Marc Gravell

1
@nawfal, làm thế nào là Copynhanh hơn CopyTo? Quan tâm đến công phu?
skrebbel

1
@skrebbel của tôi là một nhận xét không chính xác. Tôi đã thực hiện một số thử nghiệm sau đó và tôi thấy Sao chép nhanh hơn. Nhưng bây giờ có vẻ như họ chỉ bằng nhau. Những gì tôi có thể đã tìm thấy sau đó có thể là tổng thể cách tiếp cận của Marc hiệu quả hơn vì anh ta đã đưa lại ví dụ tương tự trong khi theo cách tiếp cận của Zed, anh ta đang tạo ra một mảng mới. Lời xin lỗi :)
nawfal

1
@Shimmy Nó sẽ không. Bên trong phương thức x này là một biến cục bộ, truyền x dưới dạng ref cho phương thức thay đổi kích thước sẽ tạo ra một mảng mới và thay đổi (biến cục bộ) x để trỏ đến nó. Hoặc để định nghĩa lại: x được truyền vào thay đổi kích thước và x bên trong phương thức mở rộng là cùng một biến, nhưng x không được truyền vào phương thức mở rộng dưới dạng ref, vì vậy x là một biến khác với biến trong phạm vi mà tiện ích mở rộng này được gọi từ .
AnorZaken

40

Tôi giải quyết một giải pháp đa năng hơn cho phép ghép một tập hợp các mảng một chiều tùy ý cùng loại. (Tôi đã ghép 3+ cùng một lúc.)

Chức năng của tôi:

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

Và cách sử dụng:

        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}

Chức năng tốt đẹp, cảm ơn! Thay đổi params T[][]để this T[][]làm cho nó một phần mở rộng.
Đánh dấu

Xin chào các bạn, chức năng này trông giống như những gì tôi đang tìm kiếm nhưng có ý tưởng nào để tôi đạt được điều này? link @Mark
George B

31

Đây là nó:

using System.Linq;

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

// Concatenate array1 and array2.
var result1 = array1.Concat(array2);

4
Ý tôi là int[] result = array1.ToList().Concat(array2.ToList()).toArray();Bạn không thể áp dụng Concat trên mảng trực tiếp mà tôi tin
Michail Michailidis

4
Giải pháp này - z = x.Concat (y) - được đề cập trong câu hỏi ban đầu ở trên.
Jon Schneider

1
Đây là những gì xảy ra mà không cótoArray() Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string[]'. An explicit conversion exists (are you missing a cast?)
Tibor Udvari

2
Đây không phải là một câu trả lời trực tiếp. OP yêu cầu int[] result = ?, bạn đang che giấu vấn đề câu trả lời của bạn đằng sau varrằng kết quả của bạn sẽ là IEnumerable<int>, không int[]. (một trong những lý do khiến tôi không thích varphương thức trả về)
David S.

2
Phương pháp này là những gì được sử dụng trong câu hỏi vì vậy câu trả lời này không cung cấp thông tin mới và nếu không có .ToArray()cuộc gọi, mã này sẽ không trả về một mảng thực tế nên đó cũng là một câu trả lời không chính xác.
Mani Gandham

10

Bạn có thể tắt cuộc gọi ToArray (). Có một lý do bạn cần nó là một mảng sau cuộc gọi đến Concat?

Gọi Concat tạo ra một iterator trên cả hai mảng. Nó không tạo ra một mảng mới, do đó bạn không sử dụng thêm bộ nhớ cho một mảng mới. Khi bạn gọi ToArray, bạn thực sự tạo một mảng mới và chiếm bộ nhớ cho mảng mới.

Vì vậy, nếu bạn chỉ cần dễ dàng lặp đi lặp lại trên cả hai thì chỉ cần gọi Concat.


8

Tôi biết OP chỉ hơi tò mò về hiệu suất. Các mảng lớn hơn có thể nhận được một kết quả khác (xem @kurdishTree). Và điều đó thường không thành vấn đề (@ jordan.peoples). Dù sao đi nữa, tôi đã tò mò và do đó mất trí (vì @TigerShark đang giải thích) .... Ý tôi là tôi đã viết một bài kiểm tra đơn giản dựa trên câu hỏi ban đầu .... và tất cả các câu trả lời ....

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

}

Kết quả là:

nhập mô tả hình ảnh ở đây

Cuộn chiến thắng của riêng bạn.


Để công bằng cho các phương thức đã sử dụng các phương thức, các Phương thức có thể đã thêm khoảng 10.000 tick vào hệ thống của tôi.
hợp nhất

1
Tôi đã chạy mã của bạn trong visual studio 2013 ở chế độ phát hành và thấy rằng, nếu mảng được kiểm tra không quá nhỏ như của bạn (như 1000 phần tử), CopyTosẽ nhanh nhất và nhanh hơn ~ 3x Roll your own.
Ông Ree

@ Mr.Ree Vâng, mảng của tôi thực sự rất nhỏ phải không. Cảm ơn. Sẽ được quan tâm để xem liệu Sao chép khối thậm chí còn tốt hơn ...
hợp nhất

7

Hãy cẩn thận với Concatphương pháp. Bài viết Ghép mảng trong C # giải thích rằng:

var z = x.Concat(y).ToArray();

Sẽ không hiệu quả cho các mảng lớn. Điều đó có nghĩa là Concatphương thức này chỉ dành cho các mảng có kích thước trung bình (tối đa 10000 phần tử).


2
Nên làm gì với các mảng chứa hơn 10.000 phần tử?
alex

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

2
Tại StackOverflow, vui lòng không chỉ dán mã mà còn giải thích cách tiếp cận của bạn. Trong trường hợp cụ thể này, bạn cũng có thể phải giải thích câu trả lời muộn của bạn thêm vào câu trả lời đã được đưa ra (và được chấp nhận)
Gert Arnold

1
Không chắc chắn rằng "cái này" đang làm gì trước thông số đầu tiên, nhưng đối với phần còn lại, đây là một chức năng tuyệt vời. Chung và với số lượng tham số vô hạn.
Nyerguds

2
Xin chào Nyerguds. Để trả lời câu hỏi của bạn, từ khóa "này" được sử dụng để làm cho hàm trở thành một phương thức mở rộng. Để biết thêm thông tin về các phương thức mở rộng, hãy xem bài viết MSDN này
JFish222

6

Hiệu quả hơn (nhanh hơn) để sử dụng Buffer.BlockCopyhơn 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));

Tôi đã viết một chương trình thử nghiệm đơn giản "làm nóng Jitter", được biên dịch trong chế độ phát hành và chạy nó mà không cần trình gỡ lỗi đính kèm, trên máy của tôi.

Cho 10.000.000 lần lặp lại của ví dụ trong câu hỏi

Concat mất 3088ms

CopyTo mất 1079ms

BlockCopy mất 603ms

Nếu tôi thay đổi các mảng thử nghiệm thành hai chuỗi từ 0 đến 99 thì tôi nhận được kết quả tương tự như thế này,

Concat mất 45945ms

CopyTo mất 2230ms

BlockCopy mất 1689ms

Từ những kết quả này, tôi có thể khẳng định rằng các phương pháp CopyToBlockCopyhiệu quả hơn đáng kể so với Concatvà hơn nữa, nếu hiệu suất là mục tiêu, BlockCopycó giá trị hơn CopyTo.

Để báo trước câu trả lời này, nếu hiệu suất không thành vấn đề, hoặc sẽ có vài lần lặp lại chọn phương pháp bạn thấy dễ nhất. Buffer.BlockCopykhông cung cấp một số tiện ích để chuyển đổi loại ngoài phạm vi của câu hỏi này.


6

Câu trả lời muộn :-).

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

    }

3

Cấu trúc hiệu quả nhất về RAM (và CPU) để giữ mảng kết hợp sẽ là một lớp đặc biệt thực hiện IEnumerable (hoặc nếu bạn muốn thậm chí xuất phát từ Array) và liên kết nội bộ với các mảng ban đầu để đọc các giá trị. AFAIK Concat làm điều đó.

Trong mã mẫu của bạn, bạn có thể bỏ qua .ToArray (), điều này sẽ làm cho nó hiệu quả hơn.


3

Xin lỗi để hồi sinh một chủ đề cũ, nhưng làm thế nào về điều này:

static IEnumerable<T> Merge<T>(params T[][] arrays)
{
    var merged = arrays.SelectMany(arr => arr);

    foreach (var t in merged)
        yield return t;
}

Sau đó, trong mã của bạn:

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[]

Cho đến khi bạn gọi .ToArray(), .ToList()hoặc .ToDictionary(...), bộ nhớ không được phân bổ, bạn có thể tự do "xây dựng truy vấn của mình" và gọi một trong ba người đó để thực hiện nó hoặc chỉ đơn giản là đi qua tất cả chúng bằng cách sử dụng foreach (var i in z){...}mệnh đề trả về một mục tại một thời điểm từ yield return t;ở trên...

Các chức năng trên có thể được thực hiện thành một phần mở rộng như sau:

static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
    var merged = array1.Concat(array2);

    foreach (var t in merged)
        yield return t;
}

Vì vậy, trong mã, bạn có thể làm một cái gì đó như:

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[]

Phần còn lại vẫn như trước.

Một cải tiến khác cho điều này sẽ được thay đổi T[]thành IEnumerable<T>(vì vậy params T[][]sẽ trở thành params IEnumerable<T>[]) để làm cho các hàm này chấp nhận nhiều hơn là chỉ các mảng.

Hi vọng điêu nay co ich.


2

Bạn có thể làm theo cách bạn đã đề cập hoặc nếu bạn muốn thực sự thủ công về nó, bạn có thể cuộn vòng lặp của riêng mình:

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

@nawfal Tôi nghĩ rằng sẽ phụ thuộc vào kích thước mảng. Điều này đã thắng thử nghiệm kích thước mảng nhỏ của tôi.
hợp nhất

2

Tôi đã tìm thấy một giải pháp một dòng thanh lịch bằng cách sử dụng biểu thức LINQ hoặc Lambda , cả hai đều hoạt động như nhau (LINQ được chuyển đổi thành Lambda khi chương trình được biên dịch). Giải pháp hoạt động cho bất kỳ loại mảng và cho bất kỳ số lượng mảng.

Sử dụng LINQ:

public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
    return (from array in arrays
            from arr in array
            select arr).ToArray();
}

Sử dụng Lambda:

public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
    return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}

Tôi đã cung cấp cả hai cho sở thích của một người. Hiệu suất khôn ngoan @Sergey Shteyn của hoặc @ deepee1 của giải pháp là nhanh hơn một chút, biểu hiện Lambda là chậm nhất. Thời gian thực hiện phụ thuộc vào loại (các) phần tử mảng, nhưng trừ khi có hàng triệu cuộc gọi, không có sự khác biệt đáng kể giữa các phương thức.


1

Điều bạn cần nhớ là khi sử dụng LINQ, bạn đang sử dụng thực thi bị trì hoãn. Các phương pháp khác được mô tả ở đây đều hoạt động hoàn hảo, nhưng chúng được thực thi ngay lập tức. Hơn nữa, hàm Concat () có thể được tối ưu hóa theo cách bạn không thể tự thực hiện (các cuộc gọi đến API nội bộ, các cuộc gọi HĐH, v.v.). Dù sao, trừ khi bạn thực sự cần phải cố gắng và tối ưu hóa, bạn hiện đang trên con đường dẫn đến "gốc rễ của mọi tội lỗi";)


1

Hãy thử như sau:

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

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

1

Đây là câu trả lời của tôi:

int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

Phương pháp này có thể được sử dụng ở mức khởi tạo, ví dụ để xác định nối ghép tĩnh của mảng tĩnh:

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

Tuy nhiên, nó đi kèm với hai hãy cẩn thận mà bạn cần xem xét:

  • Các Concat phương pháp tạo ra một iterator trên cả hai mảng: nó không tạo ra một mảng mới, như vậy là hiệu quả về bộ nhớ sử dụng: tuy nhiên, sau đó  ToArray  sẽ phủ nhận lợi thế như vậy, vì nó sẽ thực sự tạo ra một mảng mới và chiếm bộ nhớ cho mảng mới.
  • Như @Jodrell đã nói, Concatsẽ khá kém hiệu quả đối với các mảng lớn: nó chỉ nên được sử dụng cho các mảng có kích thước trung bình.

Nếu nhắm đến hiệu suất là bắt buộc, phương pháp sau đây có thể được sử dụng thay thế:

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

Hoặc (đối với người hâm mộ một lớp):

int[] z = (from arrays in new[] { a, b, c } from arr in arrays select arr).ToArray();

Mặc dù phương pháp sau thanh lịch hơn nhiều, nhưng phương pháp trước chắc chắn tốt hơn cho hiệu suất.

Để biết thêm thông tin, xin vui lòng tham khảo bài viết này trên blog của tôi.


0

Đối với int [] những gì bạn đã làm có vẻ tốt với tôi. câu trả lời của người hiểu cũng sẽ làm việc tốt cho List<int>.


2
Concat cũng sẽ làm việc cho Danh sách <int>. Đó là điều tuyệt vời về Concat, nó hoạt động trên mọi IEnountable <>
Mike Two

0

Đối với mảng nhỏ hơn <10000 phần tử:

using System.Linq;

int firstArray = {5,4,2};
int secondArray = {3,2,1};

int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();

Tại sao sử dụng Linq khi bạn không phải?!
ina

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

Tôi nghĩ rằng giải pháp trên là chung chung & nhẹ hơn những giải pháp khác tôi thấy ở đây. Nó tổng quát hơn vì nó không giới hạn nối chỉ cho hai mảng và nhẹ hơn vì nó không sử dụng LINQ hay List.

Lưu ý giải pháp ngắn gọn và tính tổng quát được thêm vào không thêm chi phí thời gian chạy đáng kể.


Tôi khuyên bạn nên cố gắng tìm những câu hỏi mới hơn hoặc những câu hỏi không có nhiều câu trả lời - bao gồm một câu hỏi khá giống câu hỏi của bạn.
Andrew Barber

Tôi đề xuất giải pháp này bởi vì tôi nghĩ rằng nó tóm tắt những gì tốt từ những người khác. Nó được chế tạo.
drowa

-2

int [] x = new int [] {1, 2, 3}; int [] y = new int [] {4, 5};

int [] z = x.Union (y) .ToArray ();


2
Unionkhông phải là một cách rất tốt để làm điều này vì nó ngầm gọi Distinctvà loại bỏ bất kỳ bản sao nào khỏi bộ sưu tập đã tham gia. Concattốt hơn nhiều, nhưng nó đã có trong câu hỏi ban đầu.
Nhím

-3
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]);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.