Вопрос

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

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

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

Это было полезно?

Решение

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

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..

Другие советы

В С# 3.0 вы можете использовать LINQ Конкат метод, позволяющий легко это сделать:

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.

Использовать ЛИНК:

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

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

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

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

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

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

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

Проще было бы просто использовать ЛИНК:

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

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

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

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

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

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

//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 Тип-обертка, которая хранит ссылки/указатели на переданные массивы и позволяет перебирать всю коллекцию, как если бы это был обычный массив.(Полезно в HPC, графической обработке, графическом рендеринге...)

Ваш код:

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.Я опубликую их в ближайшее время и помещу ссылку здесь.

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

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

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

Если кто-то еще ищет, как объединить два массива байтов изображений:

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

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

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

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

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, но это должно быть быстрее (хотя бы немного).

Вот простой пример использования 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);

Думаю, проще некуда.

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

Удивлен, что никто больше не предоставил решение, используя 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);

Примечание:Определенно нет гарантии упорядочивания при использовании отличающихся.

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

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 }

Я предполагаю, что вы используете свои собственные типы массивов, а не встроенные массивы .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#.

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

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

Создан и расширен метод для обработки нуля.

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

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

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

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

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top