C # में दो या अधिक बाइट सरणियों को संयोजित करने का सर्वोत्तम तरीका


238

मेरे पास C # में 3 बाइट सरणियाँ हैं जिन्हें मुझे एक में संयोजित करने की आवश्यकता है। इस कार्य को पूरा करने के लिए सबसे प्रभावी तरीका क्या होगा?


3
आपकी आवश्यकताएं क्या हैं? क्या आप सरणियों का संघ ले रहे हैं या आप एक ही मूल्य के कई उदाहरणों को संरक्षित कर रहे हैं? क्या आप आइटम को क्रमबद्ध करना चाहते हैं, या क्या आप प्रारंभिक सरणियों में ऑर्डर को संरक्षित करना चाहते हैं? क्या आप गति या कोड की लाइनों में दक्षता की तलाश कर रहे हैं?
जैसन

इसे प्यार करें, "सर्वश्रेष्ठ" इस बात पर निर्भर करता है कि आपकी आवश्यकताएं क्या हैं।
Ady

7
यदि आप LINQ का उपयोग करने में सक्षम हैं, तो आप बस Concatविधि का उपयोग कर सकते हैं :IEnumerable<byte> arrays = array1.Concat(array2).Concat(array3);
casperOne

1
कृपया अपने प्रश्नों में अधिक स्पष्ट होने का प्रयास करें। इस अस्पष्ट प्रश्न ने उन लोगों में बहुत भ्रम पैदा कर दिया है जो आपको जवाब देने के लिए पर्याप्त समय लेते हैं।
ड्रू नोक

जवाबों:


326

आदिम प्रकारों के लिए (बाइट्स सहित), के System.Buffer.BlockCopyबजाय का उपयोग करें System.Array.Copy। यह तेज है।

मैंने सुझाए गए तरीकों में से प्रत्येक को 10 बाइट्स के 3 सरणियों का उपयोग करते हुए 1 मिलियन बार लूप में निष्पादित किया है। यहाँ परिणाम हैं:

  1. नई बाइट एरे का उपयोग करते हुए System.Array.Copy - 0.2187556 सेकंड
  2. नई बाइट सरणी का उपयोग करते हुए System.Buffer.BlockCopy - 0.1406286 सेकंड
  3. IEnumerable <बाइट> C # उपज ऑपरेटर का उपयोग कर - 0.0781270 सेकंड
  4. IEnumerable <byte> LINQ's Concat <> - 0.0781270 सेकंड का उपयोग कर

मैंने प्रत्येक सरणी का आकार 100 तत्वों तक बढ़ाया और परीक्षण फिर से चलाया:

  1. नई बाइट सरणी का उपयोग कर System.Array.Copy - 0.2812554 सेकंड
  2. नई बाइट सरणी का उपयोग System.Buffer.BlockCopy - 0.2500048 सेकंड
  3. IEnumerable <बाइट> C # उपज ऑपरेटर का उपयोग करते हुए - 0.0625012 सेकंड
  4. आईनेक्स्ट के <IEteumerable <बाइट> का उपयोग कर <> - 0.0781265 सेकंड

मैंने प्रत्येक सरणी का आकार 1000 तत्वों तक बढ़ाया और परीक्षण फिर से चलाया:

  1. नई बाइट सरणी का उपयोग System.Array.Copy - 1.0781457 सेकंड
  2. नई बाइट एरे का उपयोग System.Buffer.BlockCopy - 1.0156445 सेकंड
  3. IEnumerable <बाइट> C # उपज ऑपरेटर का उपयोग करते हुए - 0.0625012 सेकंड
  4. आईनेक्स्ट के <IEteumerable <बाइट> का उपयोग कर <> - 0.0781265 सेकंड

अंत में, मैंने प्रत्येक सरणी के आकार को 1 मिलियन तत्वों तक बढ़ाया और परीक्षण को फिर से चलाया, प्रत्येक लूप को केवल 4000 बार निष्पादित किया :

  1. नई बाइट एरे का उपयोग करना System.Array.Copy - 13.4533833 सेकंड
  2. नई बाइट सरणी का उपयोग करते हुए System.Buffer.BlockCopy - 13.1096267 सेकंड
  3. IEnumerable <बाइट> C # उपज ऑपरेटर का उपयोग करना - 0 सेकंड
  4. आईनेक्यू के कॉनैट <> - 0 सेकंड का उपयोग करके IEnumerable <बाइट>

इसलिए, यदि आपको एक नई बाइट सरणी की आवश्यकता है, तो उपयोग करें

byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);

लेकिन, यदि आप एक का उपयोग कर सकते हैं IEnumerable<byte>, निश्चित रूप से LINQ के कॉनैट <> विधि को पसंद करते हैं। यह सी # उपज ऑपरेटर की तुलना में केवल थोड़ा धीमा है, लेकिन अधिक संक्षिप्त और अधिक सुरुचिपूर्ण है।

IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);

यदि आपके पास बकाया संख्या है और .NET 3.5 का उपयोग कर रहे हैं, तो आप System.Buffer.BlockCopyसमाधान को इस तरह अधिक सामान्य बना सकते हैं :

private byte[] Combine(params byte[][] arrays)
{
    byte[] rv = new byte[arrays.Sum(a => a.Length)];
    int offset = 0;
    foreach (byte[] array in arrays) {
        System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
        offset += array.Length;
    }
    return rv;
}

* नोट: उपरोक्त ब्लॉक आपको काम करने के लिए शीर्ष पर निम्नलिखित नाम स्थान को जोड़ने की आवश्यकता है।

using System.Linq;

बाद के डेटा संरचनाओं (बाइट सरणी बनाम IEnumerable <बाइट>) की पुनरावृत्ति के बारे में जॉन स्कीट की बात करने के लिए, मैंने पिछली बार परीक्षण (1 मिलियन तत्व, 4000 पुनरावृत्तियों) को फिर से चलाया, एक लूप जोड़कर जो प्रत्येक के साथ पूर्ण सरणी पर पुनरावृत्ति करता है उत्तीर्ण करना:

  1. नई बाइट ऐरे का उपयोग करते हुए System.Array.Copy - 78.20550510 सेकंड
  2. नई बाइट सरणी का उपयोग System.Buffer.BlockCopy - 77.89261900 सेकंड
  3. IEnumerable <बाइट> C # उपज ऑपरेटर का उपयोग करना - 551.7150161 सेकंड
  4. आईएनक्यूएमएरेबल <बाइट> LINQ के कॉनैट <> - 448.1804799 सेकंड का उपयोग कर

मुद्दा यह है कि निर्माण और परिणामी डेटा संरचना के उपयोग दोनों की दक्षता को समझना बहुत महत्वपूर्ण है । बस सृजन की दक्षता पर ध्यान केंद्रित करने से उपयोग से जुड़ी अक्षमता को नजरअंदाज किया जा सकता है। कुडोस, जॉन।


61
लेकिन क्या आप वास्तव में एक सरणी में इसे अंत में परिवर्तित कर रहे हैं, जैसा कि प्रश्न की आवश्यकता है? यदि नहीं, तो बेशक यह तेज़ है - लेकिन यह आवश्यकताओं को पूरा नहीं कर रहा है।
जॉन स्कीट

18
पुन: मैट डेविस - यह कोई फर्क नहीं पड़ता कि अगर आपकी "आवश्यकताओं" को IEnumerable को एक सरणी में बदलना है - यह सब आपकी आवश्यकताओं की आवश्यकता है, जिसका परिणाम वास्तव में कुछ फ़ाइज़न में उपयोग किया जाता है । IEnumerable पर आपके प्रदर्शन परीक्षण का कारण इतना कम है क्योंकि आप वास्तव में कुछ भी नहीं कर रहे हैं ! LINQ आपके किसी भी कार्य को तब तक नहीं करता है जब तक आप परिणाम का उपयोग करने का प्रयास नहीं करते हैं। इस कारण से मैं आपके उत्तर को उद्देश्यपूर्ण रूप से गलत पाता हूं और दूसरों को LINQ का उपयोग करने के लिए प्रेरित कर सकता हूं जब उन्हें प्रदर्शन के बारे में परवाह नहीं है।
सीएसउवे

12
मैंने आपका अपडेट, मेरी टिप्पणी सहित पूरा उत्तर पढ़ा। मुझे पता है कि मैं देर से पार्टी में शामिल हो रहा हूं, लेकिन इसका उत्तर घोर भ्रामक है और पहली छमाही में गलत है
csauve

14
ऐसा उत्तर क्यों है जिसमें गलत और भ्रामक जानकारी शामिल है, जो शीर्ष-मतदान का जवाब है, और मूल रूप से किसी (जॉन स्कीट) द्वारा इंगित किए जाने के बाद अपने मूल कथन को पूरी तरह से अमान्य करने के लिए संपादित किया गया था, जिसमें यह भी कहा गया था कि यह ओपीएस प्रश्न का उत्तर भी नहीं देता है?
MrCC

3
भ्रामक जवाब। यहां तक ​​कि संस्करण सवाल का जवाब नहीं दे रहा है।
सर्ज प्रोफैफिलीज़बुक

154

उत्तर में से कई मुझे बताई गई आवश्यकताओं की अनदेखी करते हैं:

  • परिणाम एक बाइट सरणी होना चाहिए
  • यह यथासंभव कुशल होना चाहिए

ये दोनों एक साथ बाइट्स के एक LINQ अनुक्रम को नियंत्रित करते हैं - कुछ भी जिसके साथ yieldपूरे अनुक्रम के माध्यम से पुनरावृत्ति के बिना अंतिम आकार प्राप्त करना असंभव है।

यदि वे पाठ्यक्रम की वास्तविक आवश्यकताएं नहीं हैं , तो LINQ पूरी तरह से एक अच्छा समाधान (या IList<T>कार्यान्वयन) हो सकता है। हालाँकि, मुझे लगता है कि सुपरडुंबेल जानता है कि वह क्या चाहता है।

(संपादित करें: मैंने अभी एक और विचार किया है। सरणियों की एक प्रति बनाने और उन्हें आलसी रूप से पढ़ने के बीच एक बड़ा अर्थपूर्ण अंतर है। विचार करें कि क्या होता है यदि आप कॉल करने के बाद "स्रोत" सरणियों में से एक में डेटा बदलते हैं Combine(या जो भी हो ) विधि लेकिन परिणाम का उपयोग करने से पहले - आलसी मूल्यांकन के साथ, वह परिवर्तन दिखाई देगा। तत्काल प्रतिलिपि के साथ, यह अलग-अलग स्थितियों में अलग-अलग व्यवहार के लिए कॉल नहीं करेगा - बस कुछ के बारे में पता होना चाहिए।)

यहाँ मेरी प्रस्तावित विधियाँ हैं - जो कि कुछ अन्य उत्तरों में निहित हैं, निश्चित ही :)

public static byte[] Combine(byte[] first, byte[] second)
{
    byte[] ret = new byte[first.Length + second.Length];
    Buffer.BlockCopy(first, 0, ret, 0, first.Length);
    Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
    return ret;
}

public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
    byte[] ret = new byte[first.Length + second.Length + third.Length];
    Buffer.BlockCopy(first, 0, ret, 0, first.Length);
    Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
    Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
                     third.Length);
    return ret;
}

public static byte[] Combine(params byte[][] arrays)
{
    byte[] ret = new byte[arrays.Sum(x => x.Length)];
    int offset = 0;
    foreach (byte[] data in arrays)
    {
        Buffer.BlockCopy(data, 0, ret, offset, data.Length);
        offset += data.Length;
    }
    return ret;
}

बेशक "परमेस" संस्करण को पहले बाइट सरणियों की एक सरणी बनाने की आवश्यकता होती है, जो अतिरिक्त अक्षमता का परिचय देती है।


जॉन, मैं ठीक-ठीक समझता हूँ कि तुम क्या कह रहे हो। मेरा एकमात्र मुद्दा यह है कि कभी-कभी किसी विशेष कार्यान्वयन को ध्यान में रखते हुए बिना किसी अन्य प्रश्न के प्रश्न पूछे जाते हैं जो अन्य समाधान मौजूद हैं। बस विकल्प की पेशकश के बिना एक उत्तर प्रदान करना मेरे लिए एक असंतोष की तरह लगता है। विचार?
मैट डेविस

1
@ मैट: हाँ, विकल्प की पेशकश करना अच्छा है - लेकिन यह समझाने के लायक है कि वे प्रश्न के उत्तर के रूप में उन्हें पास करने के बजाय विकल्प हैं । (मैं यह नहीं कह रहा हूं कि आपने ऐसा किया है - आपका उत्तर बहुत अच्छा है।)
जॉन स्कीट

4
(हालांकि मुझे लगता है कि आपके प्रदर्शन के बेंचमार्क को प्रत्येक मामले में सभी परिणामों से गुजरने के लिए समय लेना चाहिए, साथ ही, आलसी मूल्यांकन को एक अनुचित लाभ देने से बचने के लिए।)
जॉन स्कीट

1
यहां तक ​​कि "परिणाम एक सरणी होना चाहिए" की आवश्यकता को पूरा किए बिना, बस "परिणाम का उपयोग कुछ fasion में किया जाना चाहिए" की आवश्यकता को पूरा करने से LINQ गैर-इष्टतम हो जाएगा। मुझे लगता है कि परिणाम का उपयोग करने में सक्षम होने की आवश्यकता निहित होनी चाहिए!
csauve

2
@andleer: बफ़र के अलावा, बफ़र.ब्लॉककॉपी केवल आदिम प्रकारों के साथ काम करती है।
जॉन स्कीट

44

मैंने कोड स्वच्छता के लिए एक कदम आगे मैट का LINQ उदाहरण लिया:

byte[] rv = a1.Concat(a2).Concat(a3).ToArray();

मेरे मामले में, सरणियाँ छोटी हैं, इसलिए मुझे प्रदर्शन के बारे में चिंता नहीं है।


3
लघु और सरल समाधान, एक प्रदर्शन परीक्षण बहुत अच्छा होगा!
सेबस्टियन

3
यह निश्चित रूप से स्पष्ट है, पठनीय है, किसी बाहरी पुस्तकालयों / सहायकों की आवश्यकता नहीं है, और, विकास के समय के मामले में, काफी कुशल है। महान जब रन-टाइम प्रदर्शन महत्वपूर्ण नहीं है।
बिंकी

28

यदि आपको एक नई बाइट सरणी की आवश्यकता है, तो निम्नलिखित का उपयोग करें:

byte[] Combine(byte[] a1, byte[] a2, byte[] a3)
{
    byte[] ret = new byte[a1.Length + a2.Length + a3.Length];
    Array.Copy(a1, 0, ret, 0, a1.Length);
    Array.Copy(a2, 0, ret, a1.Length, a2.Length);
    Array.Copy(a3, 0, ret, a1.Length + a2.Length, a3.Length);
    return ret;
}

वैकल्पिक रूप से, यदि आपको केवल एक IEnumerable की आवश्यकता है, तो C # 2.0 उपज ऑपरेटर का उपयोग करने पर विचार करें:

IEnumerable<byte> Combine(byte[] a1, byte[] a2, byte[] a3)
{
    foreach (byte b in a1)
        yield return b;
    foreach (byte b in a2)
        yield return b;
    foreach (byte b in a3)
        yield return b;
}

मैंने बड़ी धाराओं को मिलाने के लिए आपके 2 के विकल्प के समान कुछ किया है, एक आकर्षण की तरह काम किया। :)
ग्रेग डी

2
दूसरा विकल्प बढ़िया है। +1।
आर। मार्टिनो फर्नांडिस

11

मैं वास्तव में कॉनैट का उपयोग करके कुछ मुद्दों में भाग गया ... (10 मिलियन में सरणियों के साथ, यह वास्तव में दुर्घटनाग्रस्त हो गया)।

मैंने पाया कि सरल, आसान और मेरे ऊपर दुर्घटनाग्रस्त हुए बिना अच्छी तरह से काम करता है, और यह किसी भी संख्या में सरणियों के लिए काम करता है (सिर्फ तीन नहीं) (यह LINQ का उपयोग करता है):

public static byte[] ConcatByteArrays(params byte[][]  arrays)
{
    return arrays.SelectMany(x => x).ToArray();
}

6

मेमोरीस्ट्रीम क्लास यह काम मेरे लिए बहुत अच्छी तरह से करता है। मैं बफर क्लास को मेमोरीस्ट्रीम के रूप में तेजी से चलाने के लिए नहीं मिल सका।

using (MemoryStream ms = new MemoryStream())
{
  ms.Write(BitConverter.GetBytes(22),0,4);
  ms.Write(BitConverter.GetBytes(44),0,4);
  ms.ToArray();
}

3
Qwe कहा गया है, मैं 10,000,000 बार एक पाश में एक परीक्षण किया था, और MemoryStream 290% की तुलना में Buffer.BlockCopy धीमी बाहर आया था
esac

कुछ मामलों में आप व्यक्तिगत सरणी लंबाई के किसी भी foreknowledge बिना सरणियों के एक असंख्य पर iterating हो सकता है। इस परिदृश्य में यह अच्छी तरह से काम करता है। ब्लॉकचेन एक गंतव्य सरणी होने पर निर्भर करता है
प्रिटिनल

जैसा @Sentinel ने कहा, यह उत्तर मेरे लिए एकदम सही है क्योंकि मुझे उन चीजों के आकार का कोई ज्ञान नहीं है जो मुझे लिखनी हैं और मुझे चीजों को बहुत सफाई से करने की अनुमति है। यह .NET कोर 3 के [ReadOnly] स्पैन <बाइट> के साथ भी अच्छा खेलता है!
पानी

यदि आप MemoryStream को आकार के अंतिम आकार के साथ आरंभ करते हैं तो इसे फिर से बनाया नहीं जाएगा और यह तेजी से @esac होगा।
टोनो नाम

2
    public static bool MyConcat<T>(ref T[] base_arr, ref T[] add_arr)
    {
        try
        {
            int base_size = base_arr.Length;
            int size_T = System.Runtime.InteropServices.Marshal.SizeOf(base_arr[0]);
            Array.Resize(ref base_arr, base_size + add_arr.Length);
            Buffer.BlockCopy(add_arr, 0, base_arr, base_size * size_T, add_arr.Length * size_T);
        }
        catch (IndexOutOfRangeException ioor)
        {
            MessageBox.Show(ioor.Message);
            return false;
        }
        return true;
    }

दुर्भाग्य से यह सभी प्रकारों के साथ काम नहीं करेगा। Mars.S.SOOf () कई प्रकारों के लिए एक आकार वापस करने में असमर्थ हो जाएगा (इस पद्धति का उपयोग स्ट्रिंग के सरणियों के साथ करें और आपको एक अपवाद दिखाई देगा "System.String 'को एक अप्रबंधित संरचना के रूप में मार्श नहीं किया जा सकता; ऑफसेट की गणना की जा सकती है "। आप केवल संदर्भ (प्रकार जोड़कर where T : struct) के प्रकार पैरामीटर को सीमित करने का प्रयास कर सकते हैं , लेकिन - सीएलआर के दोषों में विशेषज्ञ नहीं होने के कारण - मैं यह नहीं कह सकता कि क्या आपको कुछ निश्चित संरचना पर अपवाद मिल सकते हैं। (उदाहरण के लिए यदि उनके पास संदर्भ प्रकार के फ़ील्ड हैं)
डैनियल स्कॉट

2
    public static byte[] Concat(params byte[][] arrays) {
        using (var mem = new MemoryStream(arrays.Sum(a => a.Length))) {
            foreach (var array in arrays) {
                mem.Write(array, 0, array.Length);
            }
            return mem.ToArray();
        }
    }

यदि आप इस कोड नमूने का थोड़ा विवरण देते हैं, तो आप बेहतर जवाब दे सकते हैं।

1
यह बाइट सरणियों के एक सरणी को एक बड़े बाइट सरणी (जैसे) में परिवर्तित करता है: [1,2,3] + [4,5] + [6,7] ==> [1,2,3,4,5 , 6,7]
पीटर एर्टल

1

सरणियों को संयोजित करने के लिए जेनरिक का उपयोग कर सकते हैं। निम्नलिखित कोड को आसानी से तीन सरणियों तक विस्तारित किया जा सकता है। इस तरह आपको विभिन्न प्रकार के सरणियों के लिए कोड की नकल करने की आवश्यकता नहीं है। उपर्युक्त कुछ उत्तर मुझे अत्यधिक जटिल लगते हैं।

private static T[] CombineTwoArrays<T>(T[] a1, T[] a2)
    {
        T[] arrayCombined = new T[a1.Length + a2.Length];
        Array.Copy(a1, 0, arrayCombined, 0, a1.Length);
        Array.Copy(a2, 0, arrayCombined, a1.Length, a2.Length);
        return arrayCombined;
    }

0

यहां @Jon Skeet द्वारा दिए गए उत्तर का सामान्यीकरण है। यह मूल रूप से एक ही है, केवल यह किसी भी प्रकार के सरणी के लिए उपयोग करने योग्य है, न केवल बाइट्स के लिए:

public static T[] Combine<T>(T[] first, T[] second)
{
    T[] ret = new T[first.Length + second.Length];
    Buffer.BlockCopy(first, 0, ret, 0, first.Length);
    Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
    return ret;
}

public static T[] Combine<T>(T[] first, T[] second, T[] third)
{
    T[] ret = new T[first.Length + second.Length + third.Length];
    Buffer.BlockCopy(first, 0, ret, 0, first.Length);
    Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
    Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
                     third.Length);
    return ret;
}

public static T[] Combine<T>(params T[][] arrays)
{
    T[] ret = new T[arrays.Sum(x => x.Length)];
    int offset = 0;
    foreach (T[] data in arrays)
    {
        Buffer.BlockCopy(data, 0, ret, offset, data.Length);
        offset += data.Length;
    }
    return ret;
}

3
खतरा! ये विधियाँ किसी भी प्रकार की संपत्ति के साथ एक बाइट से अधिक लंबे समय तक काम नहीं करेंगी (बाइट सरणियों के अलावा सब कुछ बहुत अधिक)। बफ़र.ब्लॉककॉपी () बाइट की मात्रा के साथ काम करता है, सरणी तत्वों की संख्या नहीं। कारण यह आसानी से एक बाइट सरणी के साथ इस्तेमाल किया जा सकता है कि सरणी के प्रत्येक तत्व एक एकल बाइट है, इसलिए सरणी की भौतिक लंबाई तत्वों की संख्या के बराबर होती है। जॉन की बाइट को चालू करने के लिए [] जेनेरिक विधियों में विधियों को आपको एकल सरणी तत्व की बाइट-लंबाई से कई सभी ऑफ़सेट और लंबाई की आवश्यकता होगी - अन्यथा आप सभी डेटा की प्रतिलिपि नहीं बनाएंगे।
डैनियल स्कॉट

2
आम तौर पर इस काम को करने के लिए आप किसी एकल तत्व के आकार का उपयोग करके गणना करते हैं sizeof(...)और गुणा करते हैं कि आप कितने तत्वों को कॉपी करना चाहते हैं, लेकिन जेनेरिक प्रकार के साथ आकार का उपयोग नहीं किया जा सकता है। यह संभव है - कुछ प्रकारों के लिए - उपयोग करने के लिए Marshal.SizeOf(typeof(T)), लेकिन आपको कुछ प्रकारों (जैसे तार) के साथ रनटाइम त्रुटियाँ मिलेंगी। सीएलआर प्रकार के आंतरिक कामकाज के अधिक गहन ज्ञान वाला कोई व्यक्ति यहां सभी संभावित जाल को इंगित करने में सक्षम होगा। यह कहने के लिए पर्याप्त है कि जेनेरिक एरे का कॉन्सेप्टेशन विधि [ब्लॉककॉपी का उपयोग करना] लिखना तुच्छ नहीं है।
डैनियल स्कॉट

2
और अंत में - आप इस तरह से जेनेरिक एरे कॉनसेप्टेशन विधि को लगभग ठीक उसी तरह से लिख सकते हैं, जैसा कि Array.Copy का उपयोग करके ऊपर (थोड़ा कम प्रदर्शन के साथ) दिखाया गया है। बस सभी बफ़र को बदलें। बैलकॉपी कॉल को Array.Copy कॉल के साथ बदलें।
डैनियल स्कॉट

0
    /// <summary>
    /// Combine two Arrays with offset and count
    /// </summary>
    /// <param name="src1"></param>
    /// <param name="offset1"></param>
    /// <param name="count1"></param>
    /// <param name="src2"></param>
    /// <param name="offset2"></param>
    /// <param name="count2"></param>
    /// <returns></returns>
    public static T[] Combine<T>(this T[] src1, int offset1, int count1, T[] src2, int offset2, int count2) 
        => Enumerable.Range(0, count1 + count2).Select(a => (a < count1) ? src1[offset1 + a] : src2[offset2 + a - count1]).ToArray();

योगदान के लिए धन्यवाद। चूंकि पहले से ही एक दशक से अधिक समय के लिए उच्च श्रेणी के उत्तर दिए गए हैं, इसलिए यह आपके दृष्टिकोण को अलग करने वाले विवरण की पेशकश करने के लिए उपयोगी होगा। किसी को इसका उपयोग क्यों करना चाहिए जैसे कि स्वीकृत उत्तर?
जेरेमी कैनी

मुझे विस्तारित विधियों का उपयोग करना पसंद है, क्योंकि समझने के लिए स्पष्ट कोड हैं। यह कोड स्टार्ट इंडेक्स और काउंट और कॉनैट के साथ दो सरणियों का चयन करता है। साथ ही इस पद्धति को आगे बढ़ाया। तो, यह सभी प्रकार के सभी प्रकार के लिए तैयार है
मेहमत ÜNL

इससे मुझे अच्छी अनुभूति होती है! क्या आपको उस जानकारी को शामिल करने के लिए अपने प्रश्न को संपादित करने में कोई आपत्ति है? मुझे लगता है कि भविष्य के पाठकों के लिए यह महत्वपूर्ण होगा कि वे आगे बढ़ें, ताकि वे मौजूदा उत्तरों से आपके दृष्टिकोण को जल्दी से अलग कर सकें। धन्यवाद!
जेरेमी कैनी

-1

आप सभी को बाइट एरे की सूची को पास करने की आवश्यकता है और यह फ़ंक्शन आपको बाइट्स (मर्ज) के एरे को वापस कर देगा। यह सबसे अच्छा उपाय है जो मुझे लगता है :)।

public static byte[] CombineMultipleByteArrays(List<byte[]> lstByteArray)
        {
            using (var ms = new MemoryStream())
            {
                using (var doc = new iTextSharp.text.Document())
                {
                    using (var copy = new PdfSmartCopy(doc, ms))
                    {
                        doc.Open();
                        foreach (var p in lstByteArray)
                        {
                            using (var reader = new PdfReader(p))
                            {
                                copy.AddDocument(reader);
                            }
                        }

                        doc.Close();
                    }
                }
                return ms.ToArray();
            }
        }

-5

कॉनसैट सही जवाब है, लेकिन किसी कारण से एक नियंत्रित चीज़ को सबसे अधिक वोट मिल रहे हैं। यदि आपको वह उत्तर पसंद है, तो शायद आप इस सामान्य समाधान को और अधिक पसंद करेंगे:

    IEnumerable<byte> Combine(params byte[][] arrays)
    {
        foreach (byte[] a in arrays)
            foreach (byte b in a)
                yield return b;
    }

जो आपको चीजों को करने देगा जैसे:

    byte[] c = Combine(new byte[] { 0, 1, 2 }, new byte[] { 3, 4, 5 }).ToArray();

5
प्रश्न विशेष रूप से सबसे कुशल समाधान के लिए पूछता है । Enumerable.ToArray बहुत कुशल नहीं होने जा रहा है, क्योंकि यह अंतिम सरणी के आकार के साथ शुरू करने के लिए नहीं जान सकता है - जबकि हाथ से लुढ़का तकनीक कर सकते हैं।
जॉन स्कीट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.