Menggabungkan dua array di .NET


225

Apakah ada fungsi built in. NET 2.0 yang akan mengambil dua array dan menggabungkannya menjadi satu array?

Array keduanya memiliki tipe yang sama. Saya mendapatkan array ini dari fungsi yang banyak digunakan dalam basis kode saya dan tidak dapat memodifikasi fungsi untuk mengembalikan data dalam format yang berbeda.

Saya ingin menghindari menulis fungsi saya sendiri untuk menyelesaikan ini jika memungkinkan.

Jawaban:


118

Jika Anda dapat memanipulasi salah satu array, Anda dapat mengubah ukurannya sebelum melakukan salinan:

T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
int array1OriginalLength = array1.Length;
Array.Resize<T>(ref array1, array1OriginalLength + array2.Length);
Array.Copy(array2, 0, array1, array1OriginalLength, array2.Length);

Jika tidak, Anda dapat membuat array baru

T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
T[] newArray = new T[array1.Length + array2.Length];
Array.Copy(array1, newArray, array1.Length);
Array.Copy(array2, 0, newArray, array1.Length, array2.Length);

Lebih lanjut tentang metode Array yang tersedia di MSDN .


1
Bagaimana dengan .NET 4.0, ada berita?
Shimmy Weitzhandler

4
Catatan yang Array.Resizesebenarnya tidak mengubah ukuran array, itu menyalinnya. Itu sebabnya parameter pertama adalah by-ref (yang berarti kode pertama Anda mungkin tidak akan dikompilasi).
CodesInChaos

2
Saya hanya akan membuang potongan kode pertama Anda. Itu tidak menawarkan keuntungan, dan lebih sulit untuk membaca IMO.
CodesInChaos

3
Harap dicatat bahwa urutan parameter dalam contoh kode kedua untuk Array.Copy salah. Gunakan Array.Copy (array1, newArray, 0); sebagai gantinya.
marco birchler

Anda juga dapat melakukannya .. Daftar <byte> finalArray = Daftar baru <byte> (); finalArray.AddRange (array1); finalArray.AddRange (array2); ==> finalArray.toArray ();
Cédric Boivin

448

Di C # 3.0 Anda dapat menggunakan metode Concat LINQ untuk melakukannya dengan mudah:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = front.Concat(back).ToArray();

Di C # 2.0 Anda tidak memiliki cara langsung, tetapi Array.Copy mungkin solusi terbaik:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };

int[] combined = new int[front.Length + back.Length];
Array.Copy(front, combined, front.Length);
Array.Copy(back, 0, combined, front.Length, back.Length);

Ini dapat dengan mudah digunakan untuk mengimplementasikan versi Anda sendiri Concat.


1
Saya suka itu implementasi LINQ. Saya benar-benar harus melakukan lompatan dan masuk ke LINQ segera ...
GEOCHET

1
Kaya, bagian terbaik tentang implementasi LINQ tidak hanya singkat, tetapi juga seefisien versi 2.0, karena bekerja melawan IEnumerable.
Brad Wilson

Jawaban ini mencakup cara ini dan juga memberikan beberapa hasil pembandingan: stackoverflow.com/questions/415291/…
Demir

Ini mungkin cara termudah tetapi ini tidak akan efisien untuk array besar, karena Concat diimplementasikan menggunakan foreach loop + hasil (lihat sumber referensi). Solusi dengan BlockCopy akan lebih cepat.
tigrou

1
Hanya kepala kecil ke atas: jika Anda hanya ingin mengulang melalui hasil gabungan, tidak perlu mengubahnya menjadi array. Operasi terakhir itu melakukan copy array. Tidak perlu melakukan itu jika Anda mengulang melalui <n> IEnumerable. Tentu saja, mungkin ada alasan bagus untuk menjadikannya array.
Jonas

82

Gunakan LINQ :

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Union(arr2).ToArray();

Perlu diingat, ini akan menghapus duplikat. Jika Anda ingin menyimpan duplikat, gunakan Concat.


132
PERHATIAN: Serikat pekerja akan menghapus duplikat.
Yogee

1
@Yogee, mudah diingat seperti di SQL dan nomenklaturnya terhubung dengan teori himpunan.
Zbigniew Wiadro

8
karena itu akan menghapus duplikat, itu tidak akan pernah menjadi jawaban yang tepat.
Roni Tovi

1
Saya melihat Simon sudah menyebutkan masalah Union dan pendekatan alternatif yang disarankannya. Tidak perlu membahas lebih lanjut tentang itu karena Simon tahu apa yang dia jawab.
Sudhakar Chavali

41

Jika Anda tidak ingin menghapus duplikat, coba ini

Gunakan LINQ:

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Concat(arr2).ToArray();

11

Pertama, pastikan Anda bertanya pada diri sendiri pertanyaan "Haruskah saya benar-benar menggunakan Array di sini"?

Kecuali jika Anda sedang membangun sesuatu di mana kecepatan adalah yang paling penting, Daftar yang diketik, seperti List<int>mungkin adalah cara untuk pergi. Satu-satunya waktu saya pernah menggunakan array adalah untuk byte array ketika mengirim barang melalui jaringan. Selain itu, saya tidak pernah menyentuh mereka.


+1 besar di sini. Perhatikan bahwa praktik terbaik adalah untuk menghindari mengekspos List<T>di API publik: blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx
TrueWill

10

Lebih mudah hanya menggunakan LINQ :

var array = new string[] { "test" }.ToList();
var array1 = new string[] { "test" }.ToList();
array.AddRange(array1);
var result = array.ToArray();

Pertama-tama konversikan array ke daftar dan gabungkan mereka ... Setelah itu konversikan daftar kembali menjadi sebuah array :)


Anda tidak menggunakan array secara langsung. Anda menggunakan Daftar!
Behzad Ebrahimi

7

Saya pikir Anda dapat menggunakan Array . Salin untuk ini. Dibutuhkan indeks sumber dan indeks tujuan sehingga Anda harus dapat menambahkan satu array ke array lainnya. Jika Anda perlu lebih rumit daripada hanya menambahkan satu ke yang lain, ini mungkin bukan alat yang tepat untuk Anda.



4

Secara pribadi, saya lebih suka Ekstensi Bahasa saya sendiri, yang saya tambahkan atau hapus sesuka hati untuk pembuatan prototipe cepat.

Berikut ini adalah contoh untuk string.

//resides in IEnumerableStringExtensions.cs
public static class IEnumerableStringExtensions
{
   public static IEnumerable<string> Append(this string[] arrayInitial, string[] arrayToAppend)
   {
       string[] ret = new string[arrayInitial.Length + arrayToAppend.Length];
       arrayInitial.CopyTo(ret, 0);
       arrayToAppend.CopyTo(ret, arrayInitial.Length);

       return ret;
   }
}

Ini jauh lebih cepat daripada LINQ dan Concat. Lebih cepat lagi, menggunakan custom IEnumerableType-wrapper yang menyimpan referensi / pointer dari array yang dilewati dan memungkinkan perulangan seluruh koleksi seolah-olah itu adalah array normal. (Berguna dalam HPC, Pemrosesan Grafik, Pembuatan grafik ...)

Kode Anda:

var someStringArray = new[]{"a", "b", "c"};
var someStringArray2 = new[]{"d", "e", "f"};
someStringArray.Append(someStringArray2 ); //contains a,b,c,d,e,f

Untuk keseluruhan kode dan versi generik, lihat: https://gist.github.com/lsauer/7919764

Catatan: Ini mengembalikan objek IEnumerable tanpa ekstensi. Untuk mengembalikan objek yang diperluas sedikit lebih lambat.

Saya mengkompilasi ekstensi tersebut sejak 2002, dengan banyak kredit akan membantu orang-orang di CodeProject dan 'Stackoverflow'. Saya akan segera merilis ini dan meletakkan tautannya di sini.


4

Semua orang sudah memiliki pendapat mereka tetapi saya pikir ini lebih mudah dibaca daripada pendekatan "gunakan sebagai metode Extension":

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = Queryable.Concat(arr1, arr2).ToArray();

Namun itu hanya dapat digunakan saat menyatukan 2 array.


4

Inilah yang saya pikirkan. Berfungsi untuk sejumlah array.

public static T[] ConcatArrays<T>(params T[][] args)
    {
        if (args == null)
            throw new ArgumentNullException();

        var offset = 0;
        var newLength = args.Sum(arr => arr.Length); 
        var newArray = new T[newLength];

        foreach (var arr in args)
        {
            Buffer.BlockCopy(arr, 0, newArray, offset, arr.Length);
            offset += arr.Length;
        }

        return newArray;
    }

...

var header = new byte[] { 0, 1, 2};
var data = new byte[] { 3, 4, 5, 6 };
var checksum = new byte[] {7, 0};
var newArray = ConcatArrays(header, data, checksum);
//output byte[9] { 0, 1, 2, 3, 4, 5, 6, 7, 0 }

3

Untuk mencatatnya sebagai opsi: jika array yang Anda gunakan memiliki tipe primitif - Boolean (bool), Char, SByte, Byte, Int16 (pendek), UInt16, Int32 (int), UInt32, Int64 (panjang ), UInt64, IntPtr, UIntPtr, Single, atau Double - maka Anda bisa (atau harus?) Mencoba menggunakan Buffer.BlockCopy . Menurut halaman MSDN untuk kelas Buffer :

Kelas ini memberikan kinerja yang lebih baik untuk memanipulasi tipe primitif daripada metode serupa di kelas System.Array .

Menggunakan contoh C # 2.0 dari jawaban @ OwenP sebagai titik awal, ini akan berfungsi sebagai berikut:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };

int[] combined = new int[front.Length + back.Length];
Buffer.BlockCopy(front, 0, combined, 0, front.Length);
Buffer.BlockCopy(back, 0, combined, front.Length, back.Length);

Hampir tidak ada perbedaan dalam sintaksis antara Buffer.BlockCopydan Array.Copyyang @OwenP gunakan, tetapi ini harus lebih cepat (bahkan jika hanya sedikit).


2

Jika ada orang lain yang mencari cara menggabungkan dua array byte gambar:

        private void LoadImage()
        {
            string src = string.empty;
            byte[] mergedImageData = new byte[0];

            mergedImageData = MergeTwoImageByteArrays(watermarkByteArray, backgroundImageByteArray);
            src = "data:image/png;base64," + Convert.ToBase64String(mergedImageData);
            MyImage.ImageUrl = src;
        }

        private byte[] MergeTwoImageByteArrays(byte[] imageBytes, byte[] imageBaseBytes)
        {
            byte[] mergedImageData = new byte[0];
            using (var msBase = new MemoryStream(imageBaseBytes))
            {
                System.Drawing.Image imgBase = System.Drawing.Image.FromStream(msBase);
                Graphics gBase = Graphics.FromImage(imgBase);
                using (var msInfo = new MemoryStream(imageBytes))
                {
                    System.Drawing.Image imgInfo = System.Drawing.Image.FromStream(msInfo);
                    Graphics gInfo = Graphics.FromImage(imgInfo);
                    gBase.DrawImage(imgInfo, new Point(0, 0));
                    //imgBase.Save(Server.MapPath("_____testImg.png"), ImageFormat.Png);
                    MemoryStream mergedImageStream = new MemoryStream();
                    imgBase.Save(mergedImageStream, ImageFormat.Png);
                    mergedImageData = mergedImageStream.ToArray();
                    mergedImageStream.Close();
                }
            }
            return mergedImageData;
        }

1

Berikut adalah contoh sederhana menggunakan Array.CopyTo. Saya pikir itu menjawab pertanyaan Anda dan memberikan contoh penggunaan CopyTo - Saya selalu bingung ketika saya perlu menggunakan fungsi ini karena bantuannya agak tidak jelas - indeks adalah posisi di array tujuan di mana penyisipan terjadi.

int[] xSrc1 = new int[3] { 0, 1, 2 };
int[] xSrc2 = new int[5] { 3, 4, 5, 6 , 7 };

int[] xAll = new int[xSrc1.Length + xSrc2.Length];
xSrc1.CopyTo(xAll, 0);
xSrc2.CopyTo(xAll, xSrc1.Length);

Saya kira Anda tidak bisa membuatnya lebih sederhana.


1

Saya membutuhkan solusi untuk menggabungkan jumlah array yang tidak diketahui.

Heran tidak ada lagi yang memberikan solusi menggunakan SelectManydengan params.

 private static T[] Combine<T>(params IEnumerable<T>[] items) =>
                    items.SelectMany(i => i).Distinct().ToArray();

Jika Anda tidak ingin item yang berbeda, hapus saja yang berbeda.

 public string[] Reds = new [] { "Red", "Crimson", "TrafficLightRed" };
 public string[] Greens = new [] { "Green", "LimeGreen" };
 public string[] Blues = new [] { "Blue", "SkyBlue", "Navy" };

 public string[] Colors = Combine(Reds, Greens, Blues);

Catatan: Pasti tidak ada jaminan pemesanan saat menggunakan berbeda.


0

Saya berasumsi Anda menggunakan tipe array Anda sendiri sebagai lawan dari .NET array:

public string[] merge(input1, input2)
{
    string[] output = new string[input1.length + input2.length];
    for(int i = 0; i < output.length; i++)
    {
        if (i >= input1.length)
            output[i] = input2[i-input1.length];
        else
            output[i] = input1[i];
    }
    return output;
}

Cara lain untuk melakukan ini adalah dengan menggunakan kelas ArrayList bawaan.

public ArrayList merge(input1, input2)
{
    Arraylist output = new ArrayList();
    foreach(string val in input1)
        output.add(val);
    foreach(string val in input2)
        output.add(val);
    return output;
}

Kedua contoh adalah C #.


0
int [] SouceArray1 = new int[] {2,1,3};
int [] SourceArray2 = new int[] {4,5,6};
int [] targetArray = new int [SouceArray1.Length + SourceArray2.Length];
SouceArray1.CopyTo(targetArray,0);
SourceArray2.CopyTo(targetArray,SouceArray1.Length) ; 
foreach (int i in targetArray) Console.WriteLine(i + " ");  

Menggunakan kode di atas dua Array dapat dengan mudah digabungkan.


0

Dibuat dan metode ekstensi untuk menangani null

public static class IEnumerableExtenions
{
    public static IEnumerable<T> UnionIfNotNull<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
    {
        if (list1 != null && list2 != null)
            return list1.Union(list2);
        else if (list1 != null)
            return list1;
        else if (list2 != null)
            return list2;
        else return null;
    }
}

0

Jika Anda memiliki array sumber di dalam array itu sendiri, Anda dapat menggunakan SelectMany :

var arrays = new[]{new[]{1, 2, 3}, new[]{4, 5, 6}};
var combined = arrays.SelectMany(a => a).ToArray();
foreach (var v in combined) Console.WriteLine(v);   

memberi

1
2
3
4
5
6

Mungkin ini bukan metode tercepat tetapi mungkin cocok tergantung pada usecase.


-1

Kode ini akan berfungsi untuk semua kasus:

int[] a1 ={3,4,5,6};
int[] a2 = {4,7,9};
int i = a1.Length-1;
int j = a2.Length-1;
int resultIndex=  i+j+1;
Array.Resize(ref a2, a1.Length +a2.Length);
while(resultIndex >=0)
{
    if(i != 0 && j !=0)
    {
        if(a1[i] > a2[j])
        {
            a2[resultIndex--] = a[i--];
        }
        else
        {
            a2[resultIndex--] = a[j--];
        }
    }
    else if(i>=0 && j<=0)
    { 
        a2[resultIndex--] = a[i--];
    }
    else if(j>=0 && i <=0)
    {
       a2[resultIndex--] = a[j--];
    }
}

Bisakah Anda menambahkan deskripsi lebih lanjut tentang solusi yang Anda berikan?
abarisone

1
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
gunr2171

Ini tampaknya merupakan penggabungan yang diurutkan, yang walaupun berguna dalam haknya sendiri (terutama sebagai bagian dari strategi rekursif MergeSort), mungkin lebih dari yang diminta OP.
Darrel Hoffman

Sementara solusi ini bekerja, memiliki banyak teknik yang tersedia sejak C # dan VB.Net diperkenalkan, orang mungkin tidak suka solusi tersebut.
Sudhakar Chavali

-2

Coba ini:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.