मौजूदा सरणी से उप-सरणी प्राप्त करना


335

मेरे पास 10 तत्वों की एक सरणी X है। मैं X से सभी तत्वों से युक्त एक नया सरणी बनाना चाहूंगा जो कि सूचकांक 3 से शुरू होता है और सूचकांक 7 में समाप्त होता है। यकीन है कि मैं आसानी से एक लूप लिख सकता हूं जो इसे मेरे लिए करेगा लेकिन मैं अपने कोड को यथासंभव साफ रखना चाहूंगा । क्या C # में एक विधि है जो मेरे लिए कर सकती है?

कुछ इस तरह (छद्म कोड):

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

Array.Copyमेरी आवश्यकताओं के अनुरूप नहीं है । मुझे नए एरे में आइटम क्लोन करने की आवश्यकता है। Array.copyयह सिर्फ एक सी-स्टाइल के memcpyबराबर है, यह वह नहीं है जिसकी मुझे तलाश है।



7
@ कीर्तन - कि "डुबकी" विशेष रूप से IEnumerable <T> चाहता है - जो अलग है और एक अलग इष्टतम समाधान है; IMO
मार्क Gravell

तो, दो लाइनें जो इसे नई सरणी घोषित करने और कॉल करने के लिए कहेंगी। कोपी () "क्लीन कोड" नहीं है?
एड एस।

2
@Ed Swangren - नहीं करता है, तो आप एक श्रृंखलित अभिव्यक्ति के बीच में यह क्या करने की जरूरत है, कोई ;-p
मार्क Gravell

2
ShaggyUk का उत्तर संभवत: सही है: stackoverflow.com/questions/943635/…
Dykam

जवाबों:


469

आप इसे विस्तार विधि के रूप में जोड़ सकते हैं:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

पुन: क्लोनिंग अपडेट करें (जो मूल प्रश्न में स्पष्ट नहीं था)। यदि आप वास्तव में एक गहरी क्लोन चाहते हैं; कुछ इस तरह:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

इसके लिए वस्तुओं को क्रमबद्ध ( [Serializable]या ISerializable) होने की आवश्यकता होती है , हालांकि। - आप आसानी से के रूप में उपयुक्त किसी अन्य serializer के लिए स्थानापन्न कर सकता है XmlSerializer, DataContractSerializer, Protobuf शुद्ध, आदि

ध्यान दें कि गहरी क्लोनिंग बिना क्रमांकन के मुश्किल है; विशेष रूप से, ICloneableज्यादातर मामलों में भरोसा करना मुश्किल है।


1
(जाहिर है बल्कि एक लंबाई से समाप्त सूचकांक का उपयोग कर एक सरल परिवर्तन है, मैं पोस्ट किया है "जैसा है" क्योंकि है कि और अधिक "विशिष्ट" उपयोग है)
मार्क Gravell

1
फिर ... कठिन; यह ऐसा नहीं करता है .... आपको शायद कुछ इसी तरह हासिल करने के लिए क्रमांकन का उपयोग करना होगा
मार्क ग्रेवेल

1
कुछ वैकल्पिकों के लिए मेरा जवाब और कई कार्यान्वयनों के लिए एक लिंक देखें। एक उप-सरणी के लिए करने के बारे में यह हिस्सा वास्तव में तुच्छ है, जो आप वास्तव में चाहते हैं वह क्लोनिंग बिट है और यह एक जटिल और कुछ हद तक खुला प्रश्न है जो पूरी तरह से आपकी अपेक्षाओं पर निर्भर करता है कि 'सही' व्यवहार क्या होना चाहिए
शुग्गीकोउक

2
यह अच्छा है। और यह विशेष रूप से यह इंगित करना अच्छा है कि ICloneable अविश्वसनीय है, क्योंकि ओह, क्या यह कभी है।
मार्कस ग्रिप 19

1
सी # में गहरी क्लोनिंग के साथ समस्याओं को रेखांकित करने के लिए धन्यवाद। यह वास्तव में शर्म की बात है, क्योंकि गहरी नकल एक मौलिक ऑपरेशन है
दिमित्री सी।

316

आपके Array.Copy(...)द्वारा बनाए जाने के बाद आप नए सरणी में कॉपी करने के लिए उपयोग कर सकते हैं , लेकिन मुझे नहीं लगता कि कोई ऐसा तरीका है जो नए सरणी बनाता है और कई तत्वों की प्रतिलिपि बनाता है ।

यदि आप .NET 3.5 का उपयोग कर रहे हैं, तो आप LINQ का उपयोग कर सकते हैं:

var newArray = array.Skip(3).Take(5).ToArray();

लेकिन यह कुछ हद तक कम कुशल होगा।

अधिक विशिष्ट स्थितियों के लिए विकल्पों के समान प्रश्न के लिए इस उत्तर को देखें ।


+1 मुझे यह भिन्नता भी पसंद है। जॉन, क्या आप इस पर विस्तार कर सकते हैं कि इसे कम कुशल क्यों माना जाता है?
इयान रोके

@ जॉन: सवाल का मिलान करने के लिए, "टेक (5)" नहीं होगा? @Ian: Array.Copy दृष्टिकोण एक प्रगणक को शामिल नहीं करता है, और सबसे-संभावना एक सीधे memcopy हो जाएगा ...
मार्क Gravell

@Marc: हाँ वास्तव में। बहुत सवाल स्किमिंग :)
जॉन स्कीट

11
@ इयान: LINQ अप्रोच दो स्तरों के इनडायरेक्शन (पुनरावृत्तियों) का परिचय देता है, स्पष्ट रूप से वस्तुओं पर छोड़ना पड़ता है, और यह नहीं जानता कि अंतिम सरणी पहले से कितनी बड़ी होने जा रही है। दो-मिलियन-एलीमेंट सरणी के दूसरे भाग को लेने पर विचार करें: एक सरल "टार्गेट एरे बनाएं, कॉपी" एप्रोच केवल अन्य तत्वों को छूने के बिना आवश्यक ब्लॉक को कॉपी करेगा, और एक बार में। LINQ दृष्टिकोण सरणी के माध्यम से तब तक चलेगा जब तक कि यह प्रारंभ बिंदु तक नहीं पहुंच जाता है, तब मान लेना शुरू करें, एक बफर का निर्माण करना (बफर आकार में वृद्धि करना और समय-समय पर प्रतिलिपि बनाना)। बहुत कम कुशल।
जॉन स्कीट

यदि 5 EndIndexm है, तो सही प्रश्न है। सरणी (3)। टेक (5-5 + 1) .ToArray (); अर्थात। array.Skip (STARTINDEX) .Take (ENDINDEX-STARTINDEX +1) .ToArray ();
क्लॉस78

73

क्या आपने उपयोग करने पर विचार किया है ArraySegment?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx


1
यह संभवतः वही करता है जो आप चाहते हैं, लेकिन यह डिफ़ॉल्ट सरणी सिंटैक्स का समर्थन नहीं करता है, न ही यह IEnumerable का समर्थन करता है, इसलिए यह विशेष रूप से साफ नहीं है।
एलेक्स ब्लैक

5
इसके लिए अधिक उत्थान की आवश्यकता है। अपने स्वयं के विस्तार में, ArraySegment प्रतिलिपि थोड़ी तेज़ है (आखिरकार मैं गति महत्वपूर्ण सामानों के लिए सरणियों का उपयोग करता हूं) ..
nawfal

5
@AlexBlack यह .NET 4.5 की तरह दिखता है , यह IEnumerable<T>कई अन्य उपयोगी इंटरफेस को लागू करता है।
pswg

1
ArraySegmentमूल प्रश्न का उत्तर देने के लिए आप कैसे उपयोग करेंगे ?
क्रेग मैकक्वीन

2
@CraigMcQueen - प्रयास करें निम्नलिखित एकल लाइन दृष्टिकोण:IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
skia.heliou

36

मैं देखता हूं कि आप केवल संदर्भों की नकल ही नहीं, क्लोनिंग भी करना चाहते हैं। इस स्थिति में आप .Selectसरणी सदस्यों को उनके क्लोन पर प्रोजेक्ट करने के लिए उपयोग कर सकते हैं । उदाहरण के लिए, यदि आपके तत्व कार्यान्वित IClonableहैं , तो आप ऐसा कुछ कर सकते हैं:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

नोट: इस समाधान के लिए .NET फ्रेमवर्क 3.5 की आवश्यकता है।


यह अधिक सुरुचिपूर्ण है।
smwikipedia

यही वह है जिसकी तलाश में मैं हूं। यह किसी के लिए भी काम करता है IEnumerable। मैं एक मिल सकता है IEnumerable, IList, IArray, आदि, कम से कम उपद्रव के साथ ... इनलाइन अगर मैं की जरूरत है। अगर मुझे गहरी प्रति की आवश्यकता नहीं है, तो मैं अभी हटा देता हूं Select। छोड़ने Skipया Takeमुझे सीमा को नियंत्रित करने की अनुमति देता है। वैकल्पिक रूप से, मैं इसे SkipWhileऔर / या के साथ मिला सकता हूं TakeWhile
माइक

33

निम्न कोड एक पंक्ति में करता है:

// Source array
string[] Source = new string[] { "A", "B", "C", "D" };
// Extracting a slice into another array
string[] Slice = new List<string>(Source).GetRange(2, 2).ToArray();

सिंगे लाइन और लाइनक जोड़ने की जरूरत नहीं है। यह मेरा पसंदीदा तरीका है।
दिमित्री

फिर भी यह स्रोत को क्लोन नहीं करता है ... लेकिन यह वैसे भी एक अच्छा तरीका है
IG Pascual

1
यह स्रोत को क्लोन करना चाहिए क्योंकि ToArray: (1) एक नया सरणी बनाता है और (2) Array.Copy निष्पादित करता है। अंत में सोर्स और स्लाइस दो अलग-अलग ऑब्जेक्ट हैं। दृष्टिकोण सही है, फिर भी, मैं Array.Copy पसंद करते हैं: referencesource.microsoft.com/#mscorlib/system/collections/...
क्रूस

13

C # 8 में उन्होंने एक नया Rangeऔर Indexप्रकार पेश किया है

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }

12
string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();

8

मार्क के जवाब पर निर्माण लेकिन वांछित क्लोनिंग व्यवहार को जोड़ना

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}

और यदि ICloneable को लागू करना बहुत कठिन है, तो हेवार्ड स्ट्रैंडेन की कॉपी करने योग्य लाइब्रेरी का उपयोग करने के लिए एक चिंतनशील काम करना बहुत आवश्यक है।

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}

ध्यान दें कि OX.Copyable कार्यान्वयन किसी भी के साथ काम करता है:

काम करने के लिए स्वचालित प्रतिलिपि के लिए, हालांकि, निम्नलिखित कथनों में से एक को उदाहरण के लिए धारण करना चाहिए:

  • इसके प्रकार में एक पैरामीटर रहित निर्माता होना चाहिए, या
  • यह एक Copyable होना चाहिए, या
  • इसके प्रकार के लिए एक IInstanceProvider पंजीकृत होना चाहिए।

तो यह आपके पास लगभग किसी भी स्थिति को कवर करना चाहिए। यदि आप ऑब्जेक्ट को क्लोन कर रहे हैं, जहां उप ग्राफ़ में db कनेक्शन या फ़ाइल / स्ट्रीम हैंडल जैसी चीज़ें हैं, तो आपके पास स्पष्ट रूप से समस्याएँ हैं, लेकिन यह किसी भी सामान्यीकृत गहरी प्रतिलिपि के लिए सही है।

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


पहला शायद वांछित समाधान है, क्योंकि वह क्लोनिंग के लिए पूछ रहा है। ध्यान दें कि प्रतिलिपि विधि के साथ, आपको संभवतः नल की जांच करने की भी आवश्यकता नहीं है, क्योंकि यह एक विस्तार विधि है, यदि विधि पहले से ही इस बात को बताती है। एक कोशिश के काबिल है।
डायकम

हां, मैंने अशक्त जांच को नोट किया था, लेकिन ओपी को भ्रमित नहीं करना चाहता था यदि वह स्रोत नहीं पढ़ता था।
शुग्गीकोउक

2
बस एक सिडनोट: GitHub पर Copyable का नवीनतम संस्करण ऑब्जेक्ट्स को एक पैरामीटर रहित निर्माता की आवश्यकता नहीं है। :) देखें github.com/havard/copyable
Håvard S

8

आप इसे काफी आसानी से कर सकते हैं;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  

नहीं, बार अभी भी अशक्त रहेगा। Array.Copy जादुई रूप से एक नया सरणी नहीं बनाता है, खासकर जब से बार रेफरी या आउट के साथ पारित नहीं होता है।
Zr40

2
ओह, हाँ, आपका अधिकार, मैंने जल्दबाज़ी में ऐसा किया, लेकिन हे, शायद जब आपके लेखन की समालोचना में आपको सुधार करना चाहिए, तो रचनात्मक आलोचना हर किसी के लिए बहुत अधिक उपयोगी है। तो इससे पहले कि array.copy आप एक "बार = नई वस्तु [7];"
RandomNickName42

4

मुझे लगता है कि आप जिस कोड की तलाश कर रहे हैं वह है:

Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)


मुझे लगता है कि मैं यहाँ कुछ अच्छे दोस्त बना रहा हूँ .... आपके जैसे ही जवाब;) और मुझे बहुत कम वोट मिले !! हां !! किसी भी तरह, अच्छा समय अच्छा समय।
randomNickName42

3

डेटा की प्रतिलिपि बनाने के विकल्प के रूप में आप एक आवरण बना सकते हैं जो आपको मूल सरणी के एक हिस्से तक पहुंच प्रदान करता है जैसे कि यह सरणी के भाग की एक प्रतिलिपि थी। लाभ यह है कि आपको मेमोरी में डेटा की एक और कॉपी नहीं मिलती है, और डेटा को एक्सेस करते समय दोष एक मामूली ओवरहेड है।

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

उपयोग:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4

@ रॉबर्ट: नहीं, यह नहीं है। इसके बजाय एक ArraySegment का उपयोग करने का प्रयास करें, और आप देखते हैं कि आप न तो आइटम को इंडेक्स द्वारा एक्सेस कर सकते हैं, न कि आइटम्स को थ्रू आइटम।
गुफ्ता

2

Array.ConstrainedCopy काम करेगा।

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)

2
यह सिर्फ डेटा को कॉपी करता है; यह नई सरणी आदि नहीं बनाएगा; और यदि सरणी नया है, तो हम Array.Copy का उपयोग कर सकते हैं जो अधिक कुशल है (अतिरिक्त चेक / रोलबैक की कोई आवश्यकता नहीं है)।
मार्क ग्रेवेल

यह सही है, लेकिन एक नया ऐरे बनाना कोड की केवल एक पंक्ति है और किसी नए तरीके की आवश्यकता नहीं है। मैं मानता हूं कि Array.Copy भी काम करेगा।
तृष्णा

1

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

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}

1

कैसे Array.ConstrainedCopy का उपयोग करने के बारे में :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

नीचे मेरा मूल पोस्ट है। यह काम नहीं करेगा

आप Array.CopyTo का उपयोग कर सकते हैं :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

1

इस बारे में कैसा है:

public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
{
    T[] retArray = new T[endIndex - startIndex];
    for (int i = startIndex; i < endIndex; i++)
    {
        array[i - startIndex] = array[i].Clone();
    }
    return retArray;

}

फिर आपको उन सभी वर्गों पर ICloneable इंटरफ़ेस को लागू करने की आवश्यकता है जिन्हें आपको इस पर उपयोग करने की आवश्यकता है लेकिन ऐसा करना चाहिए।


1

मुझे यकीन नहीं है कि यह वास्तव में कितना गहरा है, लेकिन:

MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()

यह थोड़ा अधिक है, लेकिन यह एक अनावश्यक विधि को काट सकता है।


1

सी # 8 ने शुरू से अंत सूचकांक तक पनडुब्बी प्राप्त करने के लिए रेंज नामक सुविधा प्रदान की है। आप इसे इस तरह से उपयोग कर सकते हैं।

Index i1 = 3; // number 3 from beginning  
Index i2 = ^4; // number 4 from end  
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
var slice = a[i1..i2]; // { 3, 4, 5 }

0

जहाँ तक क्लोनिंग की बात है, मुझे नहीं लगता कि क्रमबद्धता आपके निर्माणकर्ताओं को बुलाती है। यदि आप ctor में दिलचस्प चीजें कर रहे हैं, तो यह वर्ग के आक्रमणकारियों को तोड़ सकता है।

ऐसा लगता है कि सुरक्षित प्रति आभासी है, क्लोन रचनाकारों को कॉपी कंस्ट्रक्टर कहते हैं।

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}

क्या क्रमबद्धता आपके रचनाकारों को विशिष्ट धारावाहिक निर्माता तक कहती है। कुछ करते हैं, कुछ नहीं करते। लेकिन जो आम तौर पर कॉलबैक समर्थन की पेशकश नहीं करते हैं वे आपको किसी भी आवश्यक बैकअप को करने की अनुमति देते हैं।
मार्क Gravell

यह क्रमबद्धता के एक और घर्षण बिंदु को उजागर करता है: आपको डिफ़ॉल्ट निर्माणकर्ताओं को प्रदान करना होगा।
हंस मल्हेरबे जुले

0

किसी सरणी में क्लोनिंग तत्व ऐसा कुछ नहीं है जिसे सार्वभौमिक तरीके से किया जा सके। क्या आप गहरी क्लोनिंग या सभी सदस्यों की एक साधारण प्रति चाहते हैं?

आइए "सर्वोत्तम प्रयास" दृष्टिकोण के लिए जाएं: ICloneable इंटरफ़ेस या बाइनरी सीरियलाइज़ेशन का उपयोग करके ऑब्जेक्ट्स को क्लोन करना:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

यह एक सही समाधान नहीं है, क्योंकि बस कोई भी नहीं है जो किसी भी प्रकार की वस्तु के लिए काम करेगा।


Shoudn't कि परिणाम की तरह कुछ हो [i-index] = (T) ...?
डोनाल्ड बायरड

हाँ :) और इतना ही नहीं। पाश सीमा गलत है। मैं इसे ठीक कर दूंगा। धन्यवाद!
फिलिप लेबेर्ट

0

आप Microsoft द्वारा बनाई गई कक्षा ले सकते हैं:

internal class Set<TElement>
{
    private int[] _buckets;
    private Slot[] _slots;
    private int _count;
    private int _freeList;
    private readonly IEqualityComparer<TElement> _comparer;

    public Set()
        : this(null)
    {
    }

    public Set(IEqualityComparer<TElement> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TElement>.Default;
        _comparer = comparer;
        _buckets = new int[7];
        _slots = new Slot[7];
        _freeList = -1;
    }

    public bool Add(TElement value)
    {
        return !Find(value, true);
    }

    public bool Contains(TElement value)
    {
        return Find(value, false);
    }

    public bool Remove(TElement value)
    {
        var hashCode = InternalGetHashCode(value);
        var index1 = hashCode % _buckets.Length;
        var index2 = -1;
        for (var index3 = _buckets[index1] - 1; index3 >= 0; index3 = _slots[index3].Next)
        {
            if (_slots[index3].HashCode == hashCode && _comparer.Equals(_slots[index3].Value, value))
            {
                if (index2 < 0)
                    _buckets[index1] = _slots[index3].Next + 1;
                else
                    _slots[index2].Next = _slots[index3].Next;
                _slots[index3].HashCode = -1;
                _slots[index3].Value = default(TElement);
                _slots[index3].Next = _freeList;
                _freeList = index3;
                return true;
            }
            index2 = index3;
        }
        return false;
    }

    private bool Find(TElement value, bool add)
    {
        var hashCode = InternalGetHashCode(value);
        for (var index = _buckets[hashCode % _buckets.Length] - 1; index >= 0; index = _slots[index].Next)
        {
            if (_slots[index].HashCode == hashCode && _comparer.Equals(_slots[index].Value, value))
                return true;
        }
        if (add)
        {
            int index1;
            if (_freeList >= 0)
            {
                index1 = _freeList;
                _freeList = _slots[index1].Next;
            }
            else
            {
                if (_count == _slots.Length)
                    Resize();
                index1 = _count;
                ++_count;
            }
            int index2 = hashCode % _buckets.Length;
            _slots[index1].HashCode = hashCode;
            _slots[index1].Value = value;
            _slots[index1].Next = _buckets[index2] - 1;
            _buckets[index2] = index1 + 1;
        }
        return false;
    }

    private void Resize()
    {
        var length = checked(_count * 2 + 1);
        var numArray = new int[length];
        var slotArray = new Slot[length];
        Array.Copy(_slots, 0, slotArray, 0, _count);
        for (var index1 = 0; index1 < _count; ++index1)
        {
            int index2 = slotArray[index1].HashCode % length;
            slotArray[index1].Next = numArray[index2] - 1;
            numArray[index2] = index1 + 1;
        }
        _buckets = numArray;
        _slots = slotArray;
    }

    internal int InternalGetHashCode(TElement value)
    {
        if (value != null)
            return _comparer.GetHashCode(value) & int.MaxValue;
        return 0;
    }

    internal struct Slot
    {
        internal int HashCode;
        internal TElement Value;
        internal int Next;
    }
}

और फिर

public static T[] GetSub<T>(this T[] first, T[] second)
    {
        var items = IntersectIteratorWithIndex(first, second);
        if (!items.Any()) return new T[] { };


        var index = items.First().Item2;
        var length = first.Count() - index;
        var subArray = new T[length];
        Array.Copy(first, index, subArray, 0, length);
        return subArray;
    }

    private static IEnumerable<Tuple<T, Int32>> IntersectIteratorWithIndex<T>(IEnumerable<T> first, IEnumerable<T> second)
    {
        var firstList = first.ToList();
        var set = new Set<T>();
        foreach (var i in second)
            set.Add(i);
        foreach (var i in firstList)
        {
            if (set.Remove(i))
                yield return new Tuple<T, Int32>(i, firstList.IndexOf(i));
        }
    }

0

यह इष्टतम तरीका है, मैंने ऐसा करने के लिए पाया:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

आशा है ये मदद करेगा!


0

निष्कर्षण विधि का उपयोग करें:

public static T[] Slice<T>(this T[] source, int start, int end)
    {
        // Handles negative ends.
        if (end < 0)
        {
            end = source.Length + end;
        }
        int len = end - start;

        // Return new array.
        T[] res = new T[len];
        for (int i = 0; i < len; i++)
        {
            res[i] = source[i + start];
        }
        return res;
    }

और आप इसका उपयोग कर सकते हैं

var NewArray = OldArray.Slice(3,7);

0

System.PStreet.CoreLib.dll से कोड:

public static T[] GetSubArray<T>(T[] array, Range range)
{
    if (array == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
    }
    (int Offset, int Length) offsetAndLength = range.GetOffsetAndLength(array.Length);
    int item = offsetAndLength.Offset;
    int item2 = offsetAndLength.Length;
    if (default(T) != null || typeof(T[]) == array.GetType())
    {
        if (item2 == 0)
        {
            return Array.Empty<T>();
        }
        T[] array2 = new T[item2];
        Buffer.Memmove(ref Unsafe.As<byte, T>(ref array2.GetRawSzArrayData()), ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), item), (uint)item2);
        return array2;
    }
    T[] array3 = (T[])Array.CreateInstance(array.GetType().GetElementType(), item2);
    Array.Copy(array, item, array3, 0, item2);
    return array3;
}



0

यह आपके क्लोनिंग की आवश्यकता को पूरा नहीं करता है, लेकिन ऐसा करने के लिए कई उत्तरों की तुलना में यह सरल लगता है:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();

-1
public   static   T[]   SubArray<T>(T[] data, int index, int length)
        {
            List<T> retVal = new List<T>();
            if (data == null || data.Length == 0)
                return retVal.ToArray();
            bool startRead = false;
            int count = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (i == index && !startRead)
                    startRead = true;
                if (startRead)
                {

                    retVal.Add(data[i]);
                    count++;

                    if (count == length)
                        break;
                }
            }
            return retVal.ToArray();
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.