2010-03-27 17 views
6

मैं बाइट सरणी से कई बाइट्स को हटाने के बारे में कैसे जाउंगा?पहले 16 बाइट हटाएं?

+4

एक और त्रुटिपूर्ण तो सवाल है, हम हाल ही में उनमें से एक बहुत हो रही किया गया है: यह जो कुछ उपयोग परिदृश्यों में अधिक कुशल हो सकता सरणी कॉपी करने की आवश्यकता, रोकता है। एक वाक्य के प्रश्न से अलग है जो शीर्षक की व्याख्या करने के लिए बहुत कुछ नहीं करता है। अब तक का सबसे अच्छा तरीका यह नहीं है।सरणी लेने वाली कई विधियों में एक ओवरलोड होता है जो ऑफ़सेट और लंबाई लेता है। इसके लिए एक समर्पित वर्ग भी है: ArraySegment । चाहे वह आपकी मदद करेगा, आपके प्रश्न से काफी अस्पष्ट है। शायद ऩही। –

उत्तर

24

संपादित करें: nobugz की टिप्पणी (और रीड Copsey का जवाब) का उल्लेख है, यदि आप वास्तव में एक बाइट सरणी के रूप में परिणाम की जरूरत नहीं है, आप ArraySegment<T> का उपयोग करते हुए दिखना चाहिए:

ArraySegment<byte> segment = new ArraySegment<byte>(full, 16, full.Length - 16); 

अन्यथा, नकल हो जाएगा आवश्यक - सरणी के पास हमेशा एक निश्चित आकार होता है, इसलिए आप मौजूदा सरणी से पहले 16 बाइट्स को "हटा नहीं सकते"। इसके बजाय, आपको एक नई, छोटी सरणी बनाना होगा और इसमें प्रासंगिक डेटा कॉपी करना होगा।

ज़ैक के सुझाव गैर LINQ दृष्टिकोण के लिए सही ढर्रे पर है, लेकिन यह आसान बनाया जा सकता है (यह मान लिया गया है कि आप पहले से ही पता मूल सरणी लंबे कम से कम 16 बाइट्स):

byte[] newArray = new byte[oldArray.Length - 16]; 
Buffer.BlockCopy(oldArray, 16, newArray, 0, newArray.Length); 

या

byte[] newArray = new byte[oldArray.Length - 16]; 
Array.Copy(oldArray, 16, newArray, 0, newArray.Length); 

मैं संदिग्धBuffer.BlockCopy थोड़ा तेजी से होगा, लेकिन मुझे यकीन है कि के लिए पता नहीं है।

ध्यान दें कि यदि इनमें शामिल दोनों सरणी बड़ी हैं तो LINQ दृष्टिकोण की तुलना में ये दोनों अधिक कुशल हो सकते हैं: LINQ दृष्टिकोण के लिए प्रत्येक बाइट को एक पुनरावर्तक से व्यक्तिगत रूप से वापस करने की आवश्यकता होती है, और संभावित रूप से मध्यवर्ती प्रतियां बनने की आवश्यकता होती है (उसी में List<T> पर आइटम जोड़ने के रूप में समय-समय पर बैकिंग सरणी बढ़ाना आवश्यक है)। जाहिर है माइक्रो-ऑप्टिमाइज़ नहीं करें, लेकिन यह की जांच कर रहा है यदि कोड का यह बिट एक प्रदर्शन बाधा है।

संपादित करें: मैंने तीन दृष्टिकोणों का एक बहुत "त्वरित और गंदे" बेंचमार्क चलाया। मुझे Buffer.BlockCopy और Array.Copy के बीच अंतर करने के लिए बेंचमार्क पर भरोसा नहीं है - वे बहुत करीब थे - लेकिन LINQ दृष्टिकोण 100 गुना धीमा था।

10,000 लैपटॉप के बाइट एरे का उपयोग करके, मेरे लैपटॉप पर, LINQ का उपयोग करके 40,000 प्रतियां करने में लगभग 10 सेकंड लग गए; उपर्युक्त दृष्टिकोणों ने समान मात्रा में काम करने के लिए लगभग 80ms लिया। मैंने पुनरावृत्ति गिनती को 4,000,000 तक बढ़ा दिया और इसमें अभी भी लगभग 7 सेकंड लग गए। जाहिर है सूक्ष्म-बेंचमार्क के आसपास सामान्य चेतावनी लागू होती है, लेकिन यह एक बहुत ही महत्वपूर्ण अंतर है।

निश्चित रूप से ऊपर दृष्टिकोण का उपयोग करता है, तो यह एक कोड पथ जो प्रदर्शन :) के लिए महत्वपूर्ण है में है

+0

+1, बफरिंग बड़े सरणी के लिए निश्चित रूप से अधिक कुशल है। –

+0

बफर एरे के साथ उपयोग किए जाने पर बफर.ब्लॉककॉपी और ऐरे। कॉपी के बीच क्या अंतर है? – dtb

+0

@ डीटीबी: मुझे इस मामले में कोई कार्यात्मक अंतर होने की उम्मीद नहीं है। 'बफर .ब्लॉककॉपी' थोड़ा अधिक प्रतिबंधक है - मुझे संदेह है कि इसे निम्न स्तर के तरीके में लागू किया गया है, लेकिन मुझे विवरण नहीं पता है। –

14

आप ऐसा कर सकता है:

using System.Linq 

// ... 

var newArray = oldArray.Skip(numBytes).ToArray(); 
0

आप Linq उपयोग नहीं कर सकते हैं, तो आप इसे इस तरह कर सकता है:

byte[] myArray = // however you acquire the array 

byte[] newArray = new byte[myArray.Length - 16]; 

for (int i = 0; i < newArray.Length; i++) 
{ 
    newArray[i] = myArray[i + 16]; 
} 

// newArray is now myArray minus the first 16 bytes 

तुम भी मामले को प्रबंधित करना होगा जहां सरणी 16 बाइट से कम लंबा है।

6

मैं भी उल्लेख - कैसे आप परिणाम उपयोग करने की योजना पर निर्भर करता है, अक्सर, एक वैकल्पिक दृष्टिकोण का उपयोग करने के लिए है सरणी के शेष भाग तक पहुंचने के लिए ArraySegment<T>

ArraySegment<byte> segment = new ArraySegment<byte>(originalArray, 16, originalArray.Length-16); 

// Use segment how you'd use your array... 
संबंधित मुद्दे