Arhn - архитектура программирования

Объединение двух массивов в .NET

Есть ли в .NET 2.0 встроенная функция, которая берет два массива и объединяет их в один массив?

Оба массива имеют один и тот же тип. Я получаю эти массивы из широко используемой функции в моей кодовой базе и не могу изменить функцию для возврата данных в другом формате.

Я стараюсь избегать написания моей собственной функции для достижения этой цели, если это возможно.

12.09.2008

Ответы:


1

Если вы можете манипулировать одним из массивов, вы можете изменить его размер перед копированием:

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

В противном случае вы можете создать новый массив

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

Подробнее о доступных методах массива в MSDN.

12.09.2008
  • Что насчет .NET 4.0, есть новости? 09.08.2010
  • Обратите внимание, что Array.Resize фактически не изменяет размер массива, а копирует его. Вот почему первый параметр - по ссылке (что означает, что ваш первый код, вероятно, не будет компилироваться). 16.04.2012
  • Я бы просто выбросил твой первый фрагмент кода. Это не дает преимущества, и ИМО труднее читать. 16.04.2012
  • Обратите внимание, что порядок параметров во втором примере кода для Array.Copy неправильный. Используйте Array.Copy (array1, newArray, 0); вместо. 18.04.2013
  • Вы также можете сделать это .. List ‹byte› finalArray = new List ‹byte› (); finalArray.AddRange (array1); finalArray.AddRange (array2); == ›finalArray.toArray (); 24.02.2017

  • 2

    В C # 3.0 вы можете использовать LINQ Concat, чтобы это легко сделать:

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

    В C # 2.0 такого прямого пути нет, но Array.Copy, вероятно, лучшее решение:

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

    Это можно легко использовать для реализации вашей собственной версии Concat.

    12.09.2008
  • Мне нравится эта реализация LINQ. Мне действительно нужно сделать прыжок и скоро войти в LINQ ... 12.09.2008
  • Рич, лучшая часть реализации LINQ не только в том, что она лаконична, но и так же эффективна, как версия 2.0, поскольку работает против IEnumerable. 13.09.2008
  • Этот ответ включает в себя этот способ, а также дает некоторые результаты тестирования: stackoverflow.com/questions/415291/ 09.08.2012
  • Это, вероятно, самый простой способ, но он не будет эффективным для больших массивов, поскольку Concat реализован с использованием циклов foreach + yield (см. Справочный источник). Решение с BlockCopy будет быстрее. 28.06.2017
  • .Contat () определенно самый простой. Просто подсказка из моего опыта: если вы хотите удалить дубликаты, просто вызовите .Distinct () после этого. 06.07.2017
  • Небольшое замечание: если вы хотите перебрать только объединенный результат, не нужно преобразовывать его в массив. Эта последняя операция копирует массив. Этого не будет, если вы перейдете через IEnumerable ‹int›. Конечно, могут быть веские причины, чтобы это был массив. 05.12.2018

  • 3

    Используйте LINQ:

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

    Имейте в виду, это удалит дубликаты. Если вы хотите сохранить дубликаты, используйте Concat.

    23.05.2014
  • ВНИМАНИЕ: Union удалит дубликаты. 25.06.2014
  • @Yogee, легко запомнить, как в SQL, а также номенклатура связана с теорией множеств. 25.11.2015
  • поскольку он удалит дубликаты, это никогда не может быть правильным ответом. 13.03.2016
  • Я вижу, что Саймон уже упомянул проблему Союза и альтернативный подход, который он предложил. Нет необходимости обсуждать это дальше, поскольку Саймон знает, на что отвечает. 04.12.2019

  • 4

    Если вы не хотите удалять дубликаты, попробуйте это

    Используйте LINQ:

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

    5

    Во-первых, убедитесь, что вы задаете себе вопрос: «Должен ли я действительно использовать здесь массив?»?

    Если вы не создаете что-то, где скорость имеет первостепенное значение, типизированный список, например List<int>, вероятно, будет правильным решением. Единственный раз, когда я когда-либо использовал массивы, это байтовые массивы при отправке материалов по сети. Кроме этого, я никогда их не трогаю.

    12.09.2008
  • Большой +1 здесь. Обратите внимание, что лучше всего избегать раскрытия List<T> в общедоступных API: blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx 07.01.2012

  • 6

    Проще было бы просто использовать LINQ:

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

    Сначала преобразуйте массивы в списки и объедините их ... После этого просто преобразуйте список обратно в массив :)

    25.07.2014
  • Вы не используете массив напрямую. Вы использовали List! 13.09.2019

  • 7

    Я думаю, вы можете использовать для этого Array.Copy. Он принимает исходный индекс и целевой индекс, поэтому вы можете добавить один массив к другому. Если вам нужно сделать что-то более сложное, чем просто добавить одно к другому, этот инструмент может не подойти вам.

    12.09.2008

    8

    Каждый уже высказал свое мнение, но я думаю, что это более читабельно, чем подход «использовать как метод расширения»:

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

    Однако его можно использовать только при объединении двух массивов.

    08.03.2016

    9

    Если в целевом массиве достаточно места, Array.Copy() будет работать. Вы также можете попробовать использовать List<T> и его .AddRange() метод.

    12.09.2008

    10

    Это то, что я придумал. Работает с переменным количеством массивов.

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

    11

    Лично я предпочитаю свои собственные языковые расширения, которые я добавляю или удаляю по желанию для быстрого прототипирования.

    Ниже приведен пример для строк.

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

    Это намного быстрее, чем LINQ и Concat. Еще быстрее используется пользовательский IEnumerable Type-wrapper, который хранит ссылки / указатели на переданные массивы и позволяет перебирать всю коллекцию, как если бы это был обычный массив. (Полезно в высокопроизводительных вычислениях, обработке графики, рендеринге графики ...)

    Ваш код:

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

    Полный код и универсальную версию см. На странице https://gist.github.com/lsauer/7919764

    Примечание. Это возвращает нерасширенный объект IEnumerable. Возврат расширенного объекта немного медленнее.

    Я компилирую такие расширения с 2002 года, и большое спасибо полезным людям, работающим над CodeProject и Stackoverflow. Я скоро опубликую их и разместлю здесь ссылку.

    11.12.2013

    12

    Просто чтобы отметить это как вариант: если массивы, с которыми вы работаете, имеют примитивный тип Boolean (bool), Char, SByte, Byte, Int16 (короткий), UInt16, Int32 (int), UInt32, Int64 (длинный) , UInt64, IntPtr, UIntPtr, Single или Double, тогда вы можете (или должны?) Попробовать использовать Buffer.BlockCopy. Согласно странице MSDN для класса Buffer:

    Этот класс обеспечивает лучшую производительность для управления примитивными типами, чем аналогичные методы в системе . Класс Array.

    Используя пример C # 2.0 из ответа @OwenP в качестве отправной точки, это будет работать следующим образом:

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

    Синтаксис между Buffer.BlockCopy и Array.Copy, который использовал @OwenP практически не отличается, но это должно быть быстрее (пусть даже немного).

    19.02.2017

    13

    В случае, если кто-то еще ищет, как объединить два байтовых массива изображений:

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

    14

    Мне нужно было объединить неизвестное количество массивов.

    Удивлен, что никто другой не представил решения, использующего SelectMany с params.

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

    Если вам не нужны отдельные элементы, просто удалите их.

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

    Примечание. Определенно нет никакой гарантии упорядочивания при использовании отличных.

    12.03.2018

    15

    Вот простой пример использования Array.CopyTo. Я думаю, что он отвечает на ваш вопрос и дает пример использования CopyTo - я всегда озадачен, когда мне нужно использовать эту функцию, потому что справка немного неясна - индекс - это позиция в целевом массиве, где происходит вставка.

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

    Я полагаю, вы не можете сделать это намного проще.

    18.03.2013

    16

    Если у вас есть исходные массивы в самом массиве, вы можете использовать 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);   
    

    дает

    1
    2
    3
    4
    5
    6
    

    Вероятно, это не самый быстрый метод, но он может подойти в зависимости от сценария использования.

    03.01.2020

    17

    Я предполагаю, что вы используете свои собственные типы массивов, а не встроенные массивы .NET:

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

    Другой способ сделать это - использовать встроенный класс ArrayList.

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

    Оба примера написаны на C #.

    12.09.2008

    18
    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 + " ");  
    

    Используя приведенный выше код, можно легко объединить два массива.

    14.04.2013

    19

    Создан и расширен метод для обработки 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;
        }
    }
    
    20.10.2017

    20

    Простой код для объединения нескольких массивов:

    string[] arr1 = ...
    string[] arr2 = ...
    string[] arr3 = ...    
    List<string> arr = new List<string>(arr1.Length + arr2.Length + arr3.Length);
    arr.AddRange(arr1);
    arr.AddRange(arr2);
    arr.AddRange(arr3);
    string[] result = arr.ToArray();
    
    22.03.2021

    21

    Этот код будет работать во всех случаях:

    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--];
        }
    }
    
    12.04.2015
  • Не могли бы вы подробнее рассказать о предлагаемом вами решении? 12.04.2015
  • Хотя этот фрагмент кода может решить вопрос, включение объяснения действительно помогает улучшить качество вашего поста. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода. 12.04.2015
  • Похоже, что это сортированное слияние, которое, хотя и полезно само по себе (в основном как часть рекурсивной стратегии MergeSort), может быть больше, чем просил OP. 14.01.2019
  • Хотя это решение работает, люди могут не отдавать предпочтение таким решениям, имея множество доступных методов с момента появления C # и VB.Net. 04.12.2019

  • 22

    Это еще один способ сделать это :)

    public static void ArrayPush<T>(ref T[] table, object value)
    {
        Array.Resize(ref table, table.Length + 1); // Resizing the array for the cloned length (+-) (+1)
        table.SetValue(value, table.Length - 1); // Setting the value for the new element
    }
    
    public static void MergeArrays<T>(ref T[] tableOne, T[] tableTwo) {
        foreach(var element in tableTwo) {
            ArrayPush(ref tableOne, element);
        }
    }
    

    Вот фрагмент / пример

    24.04.2021

    23

    Попробуй это:

    ArrayLIst al = new ArrayList();
    al.AddRange(array_1);
    al.AddRange(array_2);
    al.AddRange(array_3);
    array_4 = al.ToArray();
    
    07.01.2012
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..