2015-06-01 3 views
6

मेरा प्रश्न Getting a sub-array from an existing array जैसा है हालांकि मेरे मामले में थोड़ा अलग धारणा बहुत महत्वपूर्ण है - मैं स्मृति प्रतिलिपि का उपयोग नहीं कर सकता।कॉपी किए बिना सी # में किसी मौजूदा सरणी से उप-सरणी कैसे प्राप्त करें?

मैं सरणी Y कि होगा, X से 9000 तत्व शामिल हैं X के सूचकांक 500

से शुरू की जरूरत है चलो कहते हैं कि मैं सरणी 10000 के X तत्वों करते हैं, लेकिन मैं करने के लिए X का हिस्सा नकल नहीं करना चाहते नई सरणी Y, इसलिए मैं Array.Copy, Array.Clone, System.Block.Copy, IENumerables इत्यादि का उपयोग नहीं करना चाहता हूं।के संदर्भ में Y वास्तव में X[500], Y[1]X[501] से मेल खाता है, .. ।, Y[9000]X[9500] है।

इस प्रकार, उदाहरण के लिए X[100] का मूल्य बदलना Y[600] का मूल्य बदल जाएगा। मैं इसे सी # में कैसे प्राप्त कर सकता हूं?

+0

बेशक, आप 'असुरक्षित' संचालन (जैसे सी ++ पॉइंटर्स) का उपयोग कर सकते हैं, लेकिन इसकी अनुशंसा नहीं की जाती है। –

+2

क्या आपने एक साधारण रैपर बनाने पर विचार किया है जो सरणी की तरह कार्य करता है? यह * एक सरणी नहीं होगी, लेकिन यदि आपने रैपर का उपयोग करने के लिए अपना कोड लिखा है तो आप अंतर्निहित बड़ी सरणी के छोटे स्लाइस के लिए रैपर बना सकते हैं। –

+0

* क्यों * आप स्मृति प्रतिलिपि का उपयोग नहीं कर सकते? क्या कोई कारण है कि आप ऑफ़सेट पास नहीं कर सकते (शायद एक रैपर के हिस्से के रूप में, जैसे @ LasseV.Karlsen सुझाता है)? –

उत्तर

7

आप कुछ इस तरह के साथ एक और वस्तु में लपेट कर सकते हैं:

class View<T> 
{ 
    private T[] _array; 
    private long _start; 
    private long _length; 
    public View(T[] array, long start, long length) { ... } 
    public T this[long index] 
    { 
     get 
     { 
      if (/*do bounds check here*/) 
      { 
       return _array[_start + index]; 
      }  
     } 
    } 
} 

यह एक सरणी, लेकिन एक के एक प्रक्षेपण नहीं किया जाएगा।

+1

मुझे नहीं लगता कि सरणी इंडेक्स लंबे समय तक हो सकते हैं, केवल इनट्स (संख्या में है), और मैं दृश्य को एक संरचना बना दूंगा क्योंकि यह 2 32-बिट मानों को प्रभावी ढंग से रखेगा + स्मृति संदर्भ, इसे सस्ता भी बना देगा। इसके अतिरिक्त मैं फ़ील्ड को केवल पढ़ूंगा, लेकिन इसके अलावा, यह वही समाधान है जिसे मैं स्वयं चुनूंगा। –

+0

धन्यवाद, बहुत आशाजनक लग रहा है :) – xcoder37

+1

@ xcoder37 पूर्णता के लिए, 'IENumerable ' और 'IList 'के लिए समर्थन जोड़ें। –

2

आप ArraySegment का उपयोग कर सकते हैं।

String[] X = { "one", "two", "three", "four", "five"}; 

ArraySegment<String> arraySegment = new ArraySegment<String>(X, 1,3); // will contain {"two", "three", "four"} 
arraySegment.Array[arraySegment.Offset + 1] = "3"; // X will contain { "one", "two", "3", "four", "five"}; 
          // and arraySegment.Array will contain {"two", "3", "four"} 
0

दुर्भाग्य ArraySegment<T> बंद है यानी indexers और पसंद है, और आप आसानी से उचित सरणी-वाक्य रचना के साथ इसे बढ़ाया जा सकता था,: यहाँ एक उदाहरण है।

यदि मैं आप थे तो मैं ArraySegment<T> के साथ जाऊंगा और यदि इसमें उचित आवश्यकताएं नहीं हैं, जैसे ElementAt(n) अक्षम होने के लिए, बस एक बेहतर कार्यान्वयन लागू करें। पूर्व:

public static class ArrayExtensions 
{ 
    // Getter using underlying array 
    public static T GetValueAt<T>(this ArraySegment<T> array, int index) 
    { // No safe checks here, would recommend them in production though 
    return array.Array[array.Offset + index]; 
    } 
    // Setter using underlying array 
    public static void SetValueAt<T>(this ArraySegment<T> array, int index, T value) 
    { // maybe we should check that the calculated index is valid? Or just blow up? 
    array.Array[array.Offset + index] = value; 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे