2009-01-19 3 views
90

मेरे पास Foo ऑब्जेक्ट्स की एक सरणी है। मैं सरणी के दूसरे तत्व को कैसे हटा सकता हूं?नियमित सरणी के तत्व को हटाएं

मुझे RemoveAt() के समान कुछ चाहिए लेकिन नियमित सरणी के लिए।

+0

उपयोग': इसलिए, Add तत्वों के दो सेट में शामिल होने के बाद दो तरीकों से किया जा सकता है। – abatishchev

+0

मेरे खेल के लिए मैं "इंडेक्स पर नल" डेटास्ट्रक्चर के साथ गया था। असल में, आंतरिक सरणी (बफर) स्थिर आकार का है, और सूचकांक को हटाने और सरणी का आकार बदलने के बजाय, मैं केवल सूचकांक को शून्य बना देता हूं। जब मुझे कोई आइटम जोड़ने की आवश्यकता होती है तो मुझे पहले गैर-शून्य सूचकांक मिल जाता है और उसे वहां रखा जाता है। बहुत अच्छी तरह से काम करता है, लेकिन जाहिर है सब कुछ के लिए नहीं। – Krythic

उत्तर

148

आप सूची का उपयोग नहीं करना चाहते हैं:

var foos = new List<Foo>(array); 
foos.RemoveAt(index); 
return foos.ToArray(); 

आप इस एक्सटेंशन के विधि कि मैं वास्तव में परीक्षण नहीं किया की कोशिश कर सकते:

public static T[] RemoveAt<T>(this T[] source, int index) 
{ 
    T[] dest = new T[source.Length - 1]; 
    if(index > 0) 
     Array.Copy(source, 0, dest, 0, index); 

    if(index < source.Length - 1) 
     Array.Copy(source, index + 1, dest, index, source.Length - index - 1); 

    return dest; 
} 

और का उपयोग यह पसंद:

Foo[] bar = GetFoos(); 
bar = bar.RemoveAt(2); 
+6

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

+1

पाठ्यक्रम का +1, लेकिन हम भी सूची का उपयोग कर सकते हैं या सूची सूची = नई सूची (GetFoos()); सूची। हटाएं (my_foo); सूची। हटाएं (2); जहां GetFoos() Foos की सरणी वापस कर देगा !!!! – shahjapan

+1

विधि के अंदर पहली पंक्ति 'array.Length' के बजाय 'स्रोत। लम्बाई' कहनी चाहिए। – Nelson

1

यहाँ कैसे मैंने किया है ...

public static ElementDefinitionImpl[] RemoveElementDefAt(
     ElementDefinition[] oldList, 
     int removeIndex 
    ) 
    { 
     ElementDefinitionImpl[] newElementDefList = new ElementDefinitionImpl[ oldList.Length - 1 ]; 

     int offset = 0; 
     for (int index = 0; index < oldList.Length; index++) 
     { 
      ElementDefinitionImpl elementDef = oldList[ index ] as ElementDefinitionImpl; 
      if (index == removeIndex) 
      { 
       // This is the one we want to remove, so we won't copy it. But 
       // every subsequent elementDef will by shifted down by one. 
       offset = -1; 
      } 
      else 
      { 
       newElementDefList[ index + offset ] = elementDef; 
      } 
     } 
     return newElementDefList; 
    } 
54

सरणियों की प्रकृति है कि उनकी लंबाई अपरिवर्तनीय है। आप किसी भी सरणी आइटम को जोड़ या हटा नहीं सकते हैं।

आपको एक नया सरणी बनाना होगा जो एक तत्व छोटा है और पुराने आइटम को नए सरणी में कॉपी करना होगा, उस तत्व को छोड़कर जिसे आप हटाना चाहते हैं।

तो शायद सरणी के बजाय सूची का उपयोग करना बेहतर है।

+3

सरणी को सूची में बदलें 'सूची सरणी = नई सूची (arrayofmydatatype) ' –

1

एक सामान्य सरणी में आपको 2 से ऊपर की सभी सरणी प्रविष्टियों को घुमाने और फिर आकार बदलने के तरीके का आकार बदलना होगा। आप एक ArrayList का उपयोग बंद बेहतर हो सकता है।

5

यहां एक पुराना संस्करण है जो .NET ढांचे के संस्करण 1.0 पर काम करता है और जेनेरी की आवश्यकता नहीं है सी प्रकार

public static Array RemoveAt(Array source, int index) 
{ 
    if (source == null) 
     throw new ArgumentNullException("source"); 

    if (0 > index || index >= source.Length) 
     throw new ArgumentOutOfRangeException("index", index, "index is outside the bounds of source array"); 

    Array dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length - 1); 
    Array.Copy(source, 0, dest, 0, index); 
    Array.Copy(source, index + 1, dest, index, source.Length - index - 1); 

    return dest; 
} 

यह इस तरह प्रयोग किया जाता है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string[] x = new string[20]; 
     for (int i = 0; i < x.Length; i++) 
      x[i] = (i+1).ToString(); 

     string[] y = (string[])MyArrayFunctions.RemoveAt(x, 3); 

     for (int i = 0; i < y.Length; i++) 
      Console.WriteLine(y[i]); 
    } 
} 
43

मैं एक वस्तु सरणी से एक तत्व को हटाने के लिए इस विधि का उपयोग। मेरी स्थिति में, मेरे सरणी लंबाई में छोटी हैं। तो यदि आपके पास बड़े सरणी हैं तो आपको एक और समाधान की आवश्यकता हो सकती है।

private int[] RemoveIndices(int[] IndicesArray, int RemoveAt) 
{ 
    int[] newIndicesArray = new int[IndicesArray.Length - 1]; 

    int i = 0; 
    int j = 0; 
    while (i < IndicesArray.Length) 
    { 
     if (i != RemoveAt) 
     { 
      newIndicesArray[j] = IndicesArray[i]; 
      j++; 
     } 

     i++; 
    } 

    return newIndicesArray; 
} 
+5

व्यक्तिगत रूप से, मुझे यह उत्तर स्वीकार्य उत्तर से बेहतर पसंद है। यह उतना ही कुशल होना चाहिए, और इसे पढ़ने में बहुत आसान है। मैं इसे देख सकता हूं और जानता हूं कि यह सही है। मुझे यह सुनिश्चित करने के लिए दूसरे की जांच करनी होगी कि उन प्रतियों को सही तरीके से लिखा गया हो। – oillio

+0

यह वास्तव में एक शर्म की बात है कि यह जवाब इतना कम है, जब यह उपरोक्त दो से कहीं बेहतर है। – Sepulchritude

3

ऐसा नहीं है जिस तरह से इस बारे में जाने के लिए, लेकिन अगर स्थिति तुच्छ है और आप अपने समय को महत्व देते हैं, तो आप व्यर्थ प्रकार के लिए यह कोशिश कर सकते हैं।

Foos[index] = null 

और बाद में अपने तर्क में शून्य प्रविष्टियों की जांच करें ..

+0

इस तरह मैंने इसे अपने गेम के लिए किया। उन क्षेत्रों के लिए निरर्थक बफर के साथ जाएं जो अक्सर बदल जाते हैं। – Krythic

-4

प्रथम चरण
आप एक सूची में सरणी बदलने की आवश्यकता, तो आप इस

// Convert An array of string to a list of string 
public static List<string> ConnvertArrayToList(this string [] array) { 

    // DECLARE a list of string and add all element of the array into it 

    List<string> myList = new List<string>(); 
    foreach(string s in array){ 
     myList.Add(s); 
    } 
    return myList; 
} 

दूसरा कदम
जैसा कोई एक्सटेंशन विधि लिख सकता है वापस सूची कन्वर्ट करने के लिए एक विस्तार विधि लिखें एक सरणी में

// convert a list of string to an array 
public static string[] ConvertListToArray(this List<string> list) { 

    string[] array = new string[list.Capacity]; 
    array = list.Select(i => i.ToString()).ToArray(); 
    return array; 
} 

अंतिम चरणों
अपने अंतिम विधि लिखें, लेकिन कोड की तरह एक सरणी के लिए वापस परिवर्तित करने से पहले सूचकांक में तत्व को दूर करने के याद दिखाने

public static string[] removeAt(string[] array, int index) { 

    List<string> myList = array.ConnvertArrayToList(); 
    myList.RemoveAt(index); 
    return myList.ConvertListToArray(); 
} 

उदाहरण कोड, my blog पर मिल किया जा सकता है पर नज़र रखने रखने के लिए।

+12

यह 'टॉएरे()' और 'सूची ' कन्स्ट्रक्टर के अस्तित्व पर विचार करने वाला हल्का पागल है जो मौजूदा अनुक्रम लेता है ... – user7116

7

यह नेट 3.5 के रूप में, एक सरणी तत्व नष्ट करने के लिए एक तरीका है एक और सरणी को कॉपी किए बिना - Array.Resize<T> के साथ एक ही सरणी उदाहरण का उपयोग करते हुए:

public static void RemoveAt<T>(ref T[] arr, int index) 
{ 
    for (int a = index; a < arr.Length - 1; a++) 
    { 
     // moving elements downwards, to fill the gap at [index] 
     arr[a] = arr[a + 1]; 
    } 
    // finally, let's decrement Array's size by one 
    Array.Resize(ref arr, arr.Length - 1); 
} 
+0

"किसी अन्य सरणी की प्रतिलिपि के बिना" - लिंक किए गए दस्तावेज़ों के अनुसार, Array.Resize वास्तव में * करता है * दृश्यों के पीछे एक नई सरणी आवंटित करें, और पुराने सरणी से तत्वों को नए में कॉपी करें। फिर भी, मुझे इस समाधान की संक्षिप्तता पसंद है। –

+0

बहुत अच्छा और स्पष्ट है अगर आपको यकीन है कि यह अपेक्षाकृत छोटी सरणी है। – Darren

+0

@ JonSchneider की टिप्पणी जारी रखते हुए, यह "एक ही सरणी उदाहरण" नहीं है। जब आप 'आकार बदलें' विधि को कॉल करते हैं तो आपको 'ref' का उपयोग करने की आवश्यकता होती है। एक सरणी उदाहरण की लंबाई तय और अपरिवर्तनीय है। –

2

हमेशा की तरह, मैं करने के लिए देर हो रही है पार्टी ...

मैं पहले से मौजूद अच्छी समाधान सूची में एक और विकल्प जोड़ना चाहता हूं। =)
मैं इसे एक्सटेंशन के लिए एक अच्छा अवसर के रूप में देखता हूं।

संदर्भ: http://msdn.microsoft.com/en-us/library/bb311042.aspx

तो, हम कुछ स्थिर वर्ग और उस में, हमारे विधि परिभाषित करते हैं।
उसके बाद, हम अपनी विस्तारित विधि का उपयोग कर सकते हैं। =)

using System; 

namespace FunctionTesting { 

    // The class doesn't matter, as long as it's static 
    public static class SomeRandomClassWhoseNameDoesntMatter { 

     // Here's the actual method that extends arrays 
     public static T[] RemoveAt<T>(this T[] oArray, int idx) { 
      T[] nArray = new T[oArray.Length - 1]; 
      for(int i = 0; i < nArray.Length; ++i) { 
       nArray[i] = (i < idx) ? oArray[i] : oArray[i + 1]; 
      } 
      return nArray; 
     } 
    } 

    // Sample usage... 
    class Program { 
     static void Main(string[] args) { 
      string[] myStrArray = { "Zero", "One", "Two", "Three" }; 
      Console.WriteLine(String.Join(" ", myStrArray)); 
      myStrArray = myStrArray.RemoveAt(2); 
      Console.WriteLine(String.Join(" ", myStrArray)); 
      /* Output 
      * "Zero One Two Three" 
      * "Zero One Three" 
      */ 

      int[] myIntArray = { 0, 1, 2, 3 }; 
      Console.WriteLine(String.Join(" ", myIntArray)); 
      myIntArray = myIntArray.RemoveAt(2); 
      Console.WriteLine(String.Join(" ", myIntArray)); 
      /* Output 
      * "0 1 2 3" 
      * "0 1 3" 
      */ 
     } 
    } 
} 
31

LINQ एक पंक्ति का समाधान: - इस उदाहरण में, मूल प्रश्न प्रति, 2 तत्व (

myArray = myArray.Where((source, index) => index != 1).ToArray(); 

1 कि उदाहरण में हटाने तत्व के सूचकांक करने के लिए है 1 सी # शून्य-आधारित सरणी अनुक्रमण में दूसरा तत्व होने के साथ)।

एक और पूरी उदाहरण:

string[] myArray = { "a", "b", "c", "d", "e" }; 
int indexToRemove = 1; 
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray(); 

कि टुकड़ा चलाने के बाद, myArray का मूल्य { "a", "c", "d", "e" } हो जाएगा।

+0

उच्च प्रदर्शन/लगातार पहुंच की आवश्यकता वाले क्षेत्रों के लिए, LINQ की अनुशंसा नहीं की जाती है। – Krythic

+1

@ क्रिस्टिक यह एक उचित टिप्पणी है। एक तंग पाश में हजारों बार चलाएं, इस समाधान का प्रदर्शन इस पृष्ठ पर कुछ अन्य अत्यधिक वोट किए गए समाधानों के समान नहीं है: https://dotnetfiddle.net/z9Xkpn –

1
private int[] removeFromArray(int[] array, int id) 
    { 
     int difference = 0, currentValue=0; 
     //get new Array length 
     for (int i=0; i<array.Length; i++) 
     { 
      if (array[i]==id) 
      { 
       difference += 1; 
      } 
     } 
     //create new array 
     int[] newArray = new int[array.Length-difference]; 
     for (int i = 0; i < array.Length; i++) 
     { 
      if (array[i] != id) 
      { 
       newArray[currentValue] = array[i]; 
       currentValue += 1; 
      } 
     } 

     return newArray; 
    } 
0

यहां कुछ मौजूदा उत्तरों के आधार पर उत्पादित सहायक प्रकार का एक छोटा संग्रह है। ,

public static class Arr 
{ 
    public static int IndexOf<TElement>(this TElement[] Source, TElement Element) 
    { 
     for (var i = 0; i < Source.Length; i++) 
     { 
      if (Source[i].Equals(Element)) 
       return i; 
     } 

     return -1; 
    } 

    public static TElement[] Add<TElement>(ref TElement[] Source, params TElement[] Elements) 
    { 
     var OldLength = Source.Length; 
     Array.Resize(ref Source, OldLength + Elements.Length); 

     for (int j = 0, Count = Elements.Length; j < Count; j++) 
      Source[OldLength + j] = Elements[j]; 

     return Source; 
    } 

    public static TElement[] New<TElement>(params TElement[] Elements) 
    { 
     return Elements ?? new TElement[0]; 
    } 

    public static void Remove<TElement>(ref TElement[] Source, params TElement[] Elements) 
    { 
     foreach (var i in Elements) 
      RemoveAt(ref Source, Source.IndexOf(i)); 
    } 

    public static void RemoveAt<TElement>(ref TElement[] Source, int Index) 
    { 
     var Result = new TElement[Source.Length - 1]; 

     if (Index > 0) 
      Array.Copy(Source, 0, Result, 0, Index); 

     if (Index < Source.Length - 1) 
      Array.Copy(Source, Index + 1, Result, Index, Source.Length - Index - 1); 

     Source = Result; 
    } 
} 

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

IndexOf एकमात्र विस्तार तरीका है क्योंकि इसे मूल सरणी वापस करने की आवश्यकता नहीं है। New किसी प्रकार के कई तत्वों को एक प्रकार की नई सरणी बनाने के लिए स्वीकार करता है। अन्य सभी विधियों को मूल सरणी को संदर्भ के रूप में स्वीकार करना होगा, इसलिए बाद में परिणाम को असाइन करने की आवश्यकता नहीं है क्योंकि यह आंतरिक रूप से पहले से ही होता है।

मैं दो arrays विलय के लिए Merge विधि परिभाषित करता; हालांकि, यह पहले से ही एकाधिक तत्वों के विरुद्ध एक वास्तविक सरणी में गुजरकर Add विधि के साथ पूरा किया जा सकता है। `System.Collections.ObjectModel.Collection

Arr.Add<string>(ref myArray, "A", "B", "C"); 

या

Arr.Add<string>(ref myArray, anotherArray);