एक स्लाइस में तत्व को हटा दें


139
func main() {
    a := []string{"Hello1", "Hello2", "Hello3"}
    fmt.Println(a)
    // [Hello1 Hello2 Hello3]
    a = append(a[:0], a[1:]...)
    fmt.Println(a)
    // [Hello2 Hello3]
}

ऐप्पल फ़ंक्शन के साथ यह डिलीट ट्रिक कैसे काम करती है?

ऐसा लगता है कि यह पहले तत्व (खाली सरणी) से पहले सब कुछ हड़प रहा है

फिर पहले तत्व (स्थिति शून्य) के बाद सब कुछ जोड़ना

... (डॉट डॉट डॉट) क्या करता है?



3
भाषा युक्ति पर एक नज़र क्यों नहीं डालते? ...वहाँ विस्तार से बताया गया है?
वोल्कर

9
एक तरफ, बिल्कुल सच ( golang.org/ref/spec , हर कोई); दूसरी ओर, पाइथोनिस्टस आदि के प्रवास के लिए इन मुहावरों के बारे में पर्याप्त अपरिचित है, मुझे लगता है कि दूसरों को खोजने के लिए वहां स्पष्टीकरण नहीं है।
ट्वोटवोट्वो

जवाबों:


276

aटुकड़ा कहां है, और iउस तत्व का सूचकांक है जिसे आप हटाना चाहते हैं:

a = append(a[:i], a[i+1:]...)

... गो में वैरेडिक तर्कों के लिए वाक्यविन्यास है।

मूल रूप से, एक फ़ंक्शन को परिभाषित करते समय यह उन सभी तर्कों को रखता है जो आप उस प्रकार के एक स्लाइस में पास करते हैं। ऐसा करके, आप जितने चाहें उतने तर्क पारित कर सकते हैं (उदाहरण के लिए, fmt.Printlnआप जितने चाहें उतने तर्क ले सकते हैं)।

अब, जब कोई फ़ंक्शन कॉल करता है, ...तो इसके विपरीत होता है: यह एक स्लाइस को अनपैक करता है और उन्हें अलग-अलग तर्कों के रूप में पास करता है।

तो यह लाइन क्या करती है:

a = append(a[:0], a[1:]...)

अनिवार्य रूप से है:

a = append(a[:0], a[1], a[2])

अब आप सोच रहे होंगे कि ऐसा क्यों नहीं

a = append(a[1:]...)

खैर, फ़ंक्शन की परिभाषा appendहै

func append(slice []Type, elems ...Type) []Type

तो पहले तर्क में सही प्रकार का एक टुकड़ा होना चाहिए, दूसरा तर्क चर है, इसलिए हम एक खाली स्लाइस में पास करते हैं, और फिर बाकी के स्लाइस को तर्कों में भरने के लिए अनपैक करते हैं।


35
यदि मैं टुकड़ा से अंतिम तत्व है, तो क्या आप सीमा अपवाद से बाहर नहीं निकलते हैं? a = append(a[:i], a[i+1:]...)
थेमीहाई

5
@ मेरे प्रोजेक्ट में मेरे स्लाइस के साथ काम करने पर मुझे वह त्रुटि मिलती है: /
टायुगी 7

3
@ Tyguy7 कल्पना से: "सरणियों या तारों के लिए, सूचकांक सीमा में हैं यदि 0 <= कम <= उच्च <= लेन (ए), अन्यथा वे सीमा से बाहर हैं।" शायद आपके मामले में उच्च <कम; उस स्थिति में आपको त्रुटि मिलेगी। ( Golang.org/ref/spec#Slice_expressions )
MLG

2
इसका प्रदर्शन कैसा है? मुझे गंभीरता से आशा है कि यह हुड के नीचे एक पूरी तरह से नया टुकड़ा नहीं बना रहा है ..
joonas.fi

7
@ Tyguy7 मुझे लगता है कि आपने एक लूप के भीतर स्लाइस के तत्वों को हटाने की कोशिश की है। इसलिए आपको इंडेक्स से सावधान रहना होगा।
निकोले बिस्ट्रिट्सकी

42

दो विकल्प हैं:

एक: आप सरणी क्रम बनाए रखने के बारे में परवाह है:

a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

बी: आप ऑर्डर बनाए रखने के बारे में परवाह नहीं करते हैं (यह शायद तेज है):

a[i] = a[len(a)-1] // Replace it with the last one. CAREFUL only works if you have enough elements.
a = a[:len(a)-1]   // Chop off the last one.

यदि आपके व्यूअर की सरणी है तो पुन: निहितार्थ देखने के लिए लिंक देखें।

https://github.com/golang/go/wiki/SliceTricks


यह दिलचस्प है, लेकिन वास्तव में इस सवाल का जवाब नहीं है
ब्रायन

यह अच्छा है, लेकिन यह सरणी में एकमात्र तत्व को हटा सकता है तो बेहतर होगा
नागुइब इहाब

2
बस एक सिर ऊपर, ख से पहले एक प्रयोग करने का प्रयास (पिछले तत्व के साथ बदलें) नहीं स्पष्ट रूप से काम करता है आप टुकड़ा में अंतिम तत्व को निकालने का प्रयास कर रहे हैं lol
सायरन

13

तत्व सूचकांकों के रूप में [a:]-, [:b]- और - [a:b]-नोटेशन में सूचकांकों के बारे में सोचने के बजाय , उन्हें तत्वों के चारों ओर अंतराल के सूचक के रूप में और 0तत्व के रूप में अनुक्रमित होने से पहले अनुक्रमित अंतराल के साथ शुरू करने के बारे में सोचें 0

यहां छवि विवरण दर्ज करें

सिर्फ नीली संख्याओं को देखते हुए, यह देखना बहुत आसान है कि क्या चल रहा है: [0:3]सब कुछ संलग्न करता है, [3:3]खाली है और [1:2]उपज देगा {"B"}। तब [a:]का लघु संस्करण है [a:len(arrayOrSlice)], [:b]लघु संस्करण [0:b]और [:]का लघु संस्करण [0:len(arrayOrSlice)]। उत्तरार्द्ध आमतौर पर जरूरत पड़ने पर एक सरणी को एक स्लाइस में बदलने के लिए उपयोग किया जाता है।


1
यह समझाने में मदद करता है कि उत्तर क्यों "नो" है, थैथि के उत्तर पर थिइहाई की टिप्पणी का उल्लेख करते हुए, [i + 1:] यहां तक ​​कि जब ith तत्व का उल्लेख करते हैं: play.golang.org/p/E0lQ3nPcjX5
Nick P

5

... परिवर्तनशील तर्कों के लिए वाक्यविन्यास है।

मुझे लगता है कि यह स्लाइस का उपयोग करके अनिवार्य रूप से लागू किया गया है ( []Type)जैसे, फ़ंक्शन परिशिष्ट:

func append(slice []Type, elems ...Type) []Type

जब आप "एपेंड" में "एलम्स" का उपयोग करते हैं, तो वास्तव में यह एक स्लाइस ([] प्रकार) है। तो " a = append(a[:0], a[1:]...)" का अर्थ है " a = append(a[0:0], a[1:])"

a[0:0] एक टुकड़ा है जिसमें कुछ भी नहीं है

a[1:] "Hello2 Hello3" है

यह इस तरह काम करता है


2
a[0:0]nil0 लंबाई वाला एक टुकड़ा नहीं है । a[0:0]होगा ही होना nilहै, तो aहै nil
icza

5

मुझे स्वीकृत उत्तर समाधान के साथ एक त्रुटि सीमा से बाहर सूचकांक मिल रहा है। कारण: जब रेंज शुरू होती है, तो यह एक-एक करके इट्रेट वैल्यू नहीं होती है, यह इंडेक्स द्वारा इटरेट होती है। यदि आप एक स्लाइस को संशोधित करते हैं, जबकि यह सीमा में है, तो यह कुछ समस्या उत्पन्न करेगा।

पुराना उत्तर:

chars := []string{"a", "a", "b"}

for i, v := range chars {
    fmt.Printf("%+v, %d, %s\n", chars, i, v)
    if v == "a" {
        chars = append(chars[:i], chars[i+1:]...)
    }
}
fmt.Printf("%+v", chars)

अपेक्षित होना :

[a a b], 0, a
[a b], 0, a
[b], 0, b
Result: [b]

वास्तविक:

// Autual
[a a b], 0, a
[a b], 1, b
[a b], 2, b
Result: [a b]

सही तरीका (समाधान):

chars := []string{"a", "a", "b"}

for i := 0; i < len(chars); i++ {
    if chars[i] == "a" {
        chars = append(chars[:i], chars[i+1:]...)
        i-- // form the remove item index to start iterate next item
    }
}

fmt.Printf("%+v", chars)

स्रोत: https://dinolai.com/notes/golang/golang-delete-slice-item-in-range-problem.html


3

गोलंग के विकी में यह स्लाइस के लिए कुछ ट्रिक्स दिखाती है, जिसमें स्लाइस से एक तत्व को हटा दिया जाता है।

लिंक: यहां लिंक विवरण दर्ज करें

उदाहरण के लिए एक स्लाइस है जिसे आप संख्या i तत्व को हटाना चाहते हैं।

a = append(a[:i], a[i+1:]...)

या

a = a[:i+copy(a[i:], a[i+1:])]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.