سؤال

هناك المدمج في وظيفة في .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.

نصائح أخرى

في C# 3.0 يمكنك استخدام ينق Concat طريقة إنجاز هذا بسهولة:

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

في C# 2.0 لم يكن لديك مثل هذه الطريقة المباشرة ، ولكن مجموعة.نسخ هو على الارجح أفضل حل:

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.

استخدام LINQ:

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> ربما هو الطريق للذهاب.المرة الوحيدة التي كنت من أي وقت مضى استخدام المصفوفات هي البايت المصفوفات عند إرسال الأشياء عبر الشبكة.بخلاف ذلك, أنا لا تلمس لهم.

أسهل سيكون فقط باستخدام LINQ:

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

ملاحظة: هذا بإرجاع unextended IEnumerable الكائن.إلى عودة موسعة كائن هو أبطأ قليلا.

لقد جمعت هذه التمديدات منذ عام 2002 مع الكثير من الاعتمادات تذهب إلى الناس مفيدة على CodeProject و 'ستاكوفيرفلوو'.وسوف الافراج عن هؤلاء قريبا و وضع الرابط هنا.

كل شخص لديه بالفعل كان يقول ولكن أعتقد أن هذا أكثر قابلية للقراءة من "استخدام طريقة التمديد" النهج:

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

ومع ذلك فإنه يمكن أن تستخدم إلا عندما يجمع 2 المصفوفات.

في حالة شخص آخر يبحث عن كيفية دمج الصورة اثنين صفائف بايت:

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

فقط أن يكون وأشارت إلى أن خيار:إذا المصفوفات كنت تعمل مع من نوع بدائي – منطقية (منطقي) ، شار SByte, بايت, Int16 (قصيرة) ، UInt16 Int32 (int) ، UInt32, Int64 (طويلة) ، UInt64, IntPtr, UIntPtr مفرد أو مزدوج – ثم هل يمكن (أو يجب؟) حاول استخدام العازلة.BlockCopy.وفقا MSDN صفحة العازلة الدرجة:

هذه الدرجة يوفر أداء أفضل لمعالجة أنواع بدائية من أساليب مماثلة في النظام.مجموعة فئة.

باستخدام 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 تستخدم ، ولكن هذا يجب أن يكون أسرع (ولو قليلا).

هنا مثال بسيط باستخدام مجموعة.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 }

أفترض كنت تستخدم الخاصة بك أنواع مجموعة بدلا من المدمج في .صافي المصفوفات:

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

باستخدام رمز أعلاه اثنين صفائف يمكن بسهولة دمجها.

إنشاء امتداد طريقة للتعامل مع 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;
    }
}

هذا الكود يعمل على جميع الحالات:

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