.NET में दो सरणियों को जोड़ना


225

क्या कोई फ़ंक्शन .NET 2.0 में बनाया गया है जो दो सरणियों को ले जाएगा और उन्हें एक सरणी में मर्ज करेगा?

सरणियाँ दोनों एक ही प्रकार की हैं। मैं अपने कोड बेस के भीतर व्यापक रूप से उपयोग किए जाने वाले फ़ंक्शन से इन सरणियों को प्राप्त कर रहा हूं और डेटा को एक अलग प्रारूप में वापस करने के लिए फ़ंक्शन को संशोधित नहीं कर सकता।

यदि संभव हो तो इसे पूरा करने के लिए मैं अपना कार्य लिखने से बचना चाहता हूं।

जवाबों:


118

यदि आप किसी एक सारणी में फेरबदल कर सकते हैं, तो आप प्रतिलिपि करने से पहले उसका आकार बदल सकते हैं:

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 पर उपलब्ध सरणी विधियों पर अधिक


1
.NET 4.0 के बारे में, कोई भी खबर?
शिम्मी वेइटहैंडलर

4
ध्यान दें कि Array.Resizeवास्तव में सरणी का आकार नहीं होता है, यह इसे कॉपी करता है। इसीलिए पहला पैरामीटर बाई-रेफ है (जिसका अर्थ है कि आपका पहला कोड शायद संकलन नहीं करेगा)।
कोडइन्चोस

2
मैं अभी कोड का पहला टुकड़ा बाहर फेंक दूँगा। यह एक लाभ प्रदान नहीं करता है, और IMO पढ़ने के लिए कठिन है।
कोडइन्चोस

3
कृपया ध्यान दें कि Array.Copy के लिए दूसरे कोड उदाहरण में मापदंडों का क्रम गलत है। Array.Copy (array1, newArray, 0) का उपयोग करें; बजाय।
मार्को बर्चलर

आप भी कर सकते हैं .. सूची <बाइट> फाइनलअरे = नई सूची <बाइट> (); finalArray.AddRange (array1); finalArray.AddRange (array2); ==> finalArray.toArray ();
सेड्रिक बोइविन

448

C # 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


1
मुझे लगता है कि LINQ कार्यान्वयन पसंद है। मुझे वास्तव में कूदने और जल्द ही LINQ में आने की आवश्यकता है ...
GEOCHET

1
रिच, LINQ कार्यान्वयन के बारे में सबसे अच्छा हिस्सा न केवल संक्षिप्त है, यह 2.0 संस्करण के रूप में भी उतना ही कुशल है, क्योंकि यह IEnumerable के खिलाफ काम करता है।
ब्रैड विल्सन

इस उत्तर में यह तरीका शामिल है और कुछ बेंचमार्किंग परिणाम भी देता है: stackoverflow.com/questions/415291/…
डेमिर

यह शायद सबसे आसान तरीका है, लेकिन बड़े सरणियों के लिए यह कुशल नहीं है, क्योंकि कॉनकैट को फॉरेस्ट लूप्स + उपज (संदर्भ स्रोत देखें) का उपयोग करके लागू किया गया है। ब्लॉककॉपी के साथ एक समाधान तेजी से होगा।
टाइगरो

1
बस एक छोटा सा सिर: यदि आप केवल संयुक्त परिणाम के माध्यम से पुनरावृति करना चाहते हैं, तो इसे किसी सरणी में बदलने की आवश्यकता नहीं है। वह अंतिम ऑपरेशन एक सरणी कॉपी करता है। यदि आपको IEnumerable <int> के माध्यम से पुनरावृति करना है तो ऐसा नहीं करना होगा। बेशक, यह एक सरणी होने के लिए अच्छे कारण हो सकते हैं।
जोनास

82

LINQ का प्रयोग करें :

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

ध्यान रखें, यह डुप्लिकेट को हटा देगा। यदि आप डुप्लिकेट रखना चाहते हैं, तो Concat का उपयोग करें।


132
चेतावनी: संघ डुप्लिकेट निकाल देगा
योगी

1
@ योगी, याद रखना आसान है क्योंकि यह एसक्यूएल की तरह है और यह भी नामकरण सेट सिद्धांत के साथ जुड़ा हुआ है।
Zbigniew Wiadro

8
चूंकि यह डुप्लिकेट को हटा देगा, इसलिए यह कभी भी उचित उत्तर नहीं हो सकता है।
रोनी तोवी

1
मुझे लगता है कि साइमन ने पहले से ही संघ के मुद्दे का उल्लेख किया और वैकल्पिक दृष्टिकोण का सुझाव दिया। इसके बारे में आगे चर्चा करने की आवश्यकता नहीं है क्योंकि साइमन जानता है कि वह क्या जवाब दे रहा है।
सुधाकर चावली 15

41

यदि आप डुप्लिकेट नहीं निकालना चाहते हैं, तो यह प्रयास करें

LINQ का प्रयोग करें:

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

11

सबसे पहले, सुनिश्चित करें कि आप अपने आप से सवाल पूछते हैं "क्या मुझे वास्तव में यहां एक ऐरे का उपयोग करना चाहिए"?

जब तक आप कुछ ऐसा नहीं बना रहे हैं जहाँ गति का अत्यधिक महत्व है, एक टाइप की गई सूची, जैसे List<int>कि शायद जाने का रास्ता है। नेटवर्क पर सामान भेजते समय मैं केवल कभी-कभी सरणियों का उपयोग करता हूं बाइट सरणियों के लिए। उसके अलावा, मैं उन्हें कभी नहीं छूता।


यहां बड़ा +1। ध्यान दें कि List<T>सार्वजनिक एपीआई में उजागर होने से बचने के लिए सबसे अच्छा अभ्यास है : blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx
TrueWill

10

आसान बस LINQ का उपयोग किया जाएगा :

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

पहले सरणियों को सूचियों में बदलें और उन्हें मर्ज करें ... उसके बाद बस सूची को वापस सरणी में बदलें :)


आप सीधे सरणी का उपयोग नहीं कर रहे हैं। आपने सूची का उपयोग किया!
बेहज़ाद इब्राहिमी

7

मुझे लगता है कि आप इसके लिए Array.Copy का उपयोग कर सकते हैं । यह एक स्रोत सूचकांक और गंतव्य सूचकांक लेता है, इसलिए आपको एक सरणी को दूसरे में जोड़ने में सक्षम होना चाहिए। यदि आपको केवल एक से दूसरे को जोड़ने की तुलना में अधिक जटिल जाने की आवश्यकता है, तो यह आपके लिए सही उपकरण नहीं हो सकता है।


5

मान लें कि गंतव्य सरणी में पर्याप्त स्थान है, Array.Copy()काम करेगा। तुम भी एक List<T>और इसकी .AddRange()विधि का उपयोग करने की कोशिश कर सकते हैं ।


4

व्यक्तिगत रूप से, मैं अपनी स्वयं की भाषा एक्सटेंशन पसंद करता हूं, जिसे मैं तेजी से प्रोटोटाइप के लिए जोड़ या हटा देता हूं।

निम्नलिखित तार के लिए एक उदाहरण है।

//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टाइप-रैपर का उपयोग कर रहा है जो पारित सरणियों के संदर्भ / बिंदुओं को संग्रहीत करता है और पूरे संग्रह पर लूपिंग की अनुमति देता है जैसे कि यह एक सामान्य सरणी थी। (एचपीसी में उपयोगी, ग्राफिक्स प्रोसेसिंग, ग्राफिक्स रेंडर ...)

तुम्हारा कोड:

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 के बाद से ऐसे एक्सटेंशन संकलित किए हैं, जिनमें बहुत सारे क्रेडिट कोडप्रोजेक्ट और 'स्टैकओवरफ़्लो' में सहायक लोगों के पास जा रहे हैं। मैं जल्द ही इन्हें जारी करूंगा और लिंक यहां डालूंगा।


4

हर कोई पहले ही अपनी बात कह चुका है, लेकिन मुझे लगता है कि यह "एक्सटेंशन विधि के रूप में उपयोग" दृष्टिकोण से अधिक पठनीय है:

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

हालाँकि इसका उपयोग केवल 2 सरणियों को एक साथ लाने पर किया जा सकता है।


4

मैंने ये ढूंढ निकाला। चर के एक चर संख्या के लिए काम करता है।

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

बस इसे एक विकल्प के रूप में नोट किया गया है: यदि आप जिन सरणियों के साथ काम कर रहे हैं, वे एक आदिम प्रकार के हैं - बूलियन (बूल), चार, SByte, बाइट, Int16 (छोटा), UInt16, Int32 (int), UInt32, Int64 (लंबा) ), UInt64, IntPtr, UIntPtr, एकल, या डबल - फिर तुम सकता है (या होना चाहिए) का उपयोग करके देखें Buffer.BlockCopyबफ़र वर्ग के लिए MSDN पृष्ठ के अनुसार :

यह वर्ग System.Array वर्ग में समान विधियों की तुलना में आदिम प्रकारों में हेरफेर करने के लिए बेहतर प्रदर्शन प्रदान करता है ।

प्रारंभिक बिंदु के रूप में @ ओवेनपी के उत्तर से सी # 2.0 उदाहरण का उपयोग करना , यह निम्नानुसार काम करेगा:

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 इस्तेमाल किया है, लेकिन यह तेजी से (यहां तक कि केवल थोड़ा अगर) होना चाहिए।


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

1

यहाँ 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);

मुझे लगता है कि आप इसे बहुत सरल नहीं कर सकते।


1

मुझे एक अज्ञात संख्या में सरणियों के संयोजन के लिए एक समाधान की आवश्यकता थी।

हैरानी किसी और के 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);

नोट: निश्चित रूप से अलग का उपयोग करते समय आदेश की कोई गारंटी नहीं है।


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

ऐसा करने का एक और तरीका एरेलेस्ट क्लास में निर्मित का उपयोग करना होगा।

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 # हैं।


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

उपरोक्त कोड का उपयोग करके दो Arrays को आसानी से विलय किया जा सकता है।


0

अशक्त को संभालने के लिए बनाया और विस्तार विधि

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

यदि आपके पास सरणी में स्रोत सरणियाँ हैं तो आप 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

संभवतः यह सबसे तेज़ तरीका नहीं है, लेकिन usecase के आधार पर फिट हो सकता है।


-1

यह कोड सभी मामलों के लिए काम करेगा:

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

क्या आप प्रदान किए गए समाधान के बारे में अधिक विवरण जोड़ सकते हैं?
abarisone

1
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है।
गन्र

यह एक सॉर्ट किए गए मर्ज के रूप में प्रतीत होता है, जो अपने आप में उपयोगी है (मुख्य रूप से एक मर्जसर्ट पुनरावर्ती रणनीति के हिस्से के रूप में), ओपी के लिए पूछने की तुलना में अधिक हो सकता है।
डारेल हॉफमैन

जबकि यह समाधान काम करता है, C # और VB.Net के बहुत से तकनीक उपलब्ध होने के बाद लोगों को ऐसे समाधान पसंद नहीं आए।
सुधाकर चावली १६

-2

इसे इस्तेमाल करे:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.