2014-07-14 9 views
5

मैं संग्रह से तत्वों को एक जगह में हटा देना चाहता हूं। पर विचार करें निम्नलिखित स्निपेट:गोलांग स्लाइस तत्वों को हटाने में

package main 

import "fmt" 

type Ints []int 

func (xs Ints) Filter() { 
    for i := 0; i < len(xs); i++ { 
     if xs[i]%2 == 0 { // Or some other filtering function 
      xs = append(xs[:i], xs[i+1:]...) 
     } 
     fmt.Printf("i %+v\n", i) 
     fmt.Printf("xs %+v\n", xs) 
    } 
} 

func main() { 
    a := Ints([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 

    fmt.Printf("initial a %+v\n", a) 

    a.Filter() 

    fmt.Printf("final a %+v\n", a) 
} 

http://play.golang.org/p/1nL6Il2Gf1

आश्चर्यजनक परिणाम है: final a [1 3 5 7 9 10 10 10 10 10]

मुझे आश्चर्य है कि यह कैसे करना है। मुझे पूरा यकीन है कि रिसीवर को Ints पर पॉइंटर होना चाहिए। लेकिन यह कुछ हद तक कोड को गड़बड़ कर देता है (*xs हर जगह संभावित रूप से ब्रैकेट के साथ जोड़ता है) लेकिन अधिक महत्वपूर्ण बात यह है कि यह वही परिणाम उत्पन्न करता है।

उत्तर

2

मैं इसे तत्वों को ले जाकर, टुकड़ा का आकार बदलकर, और सूचक का उपयोग करके करूँगा। कुछ ऐसा:

package main 

import "fmt" 

type Ints []int 

func (xs *Ints) Filter() { 
    filterPos := 0 
    for i := 0; i < len(*xs); i++ { 
     if (*xs)[i]%2 == 0 { // Or some other filtering function 
      (*xs)[filterPos] = (*xs)[i] 
     filterPos++ 
     } 
    } 
    (*xs) = (*xs)[:filterPos] 
} 

func main() { 
    a := Ints([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 

    fmt.Printf("initial a %+v\n", a) 

    a.Filter() 

    fmt.Printf("final a %+v\n", a) 
} 
+1

बस एक छोटे से सिफारिश, उपयोग '(* XS) = (* XS) [: filterPos: filterPos]' बजाय टुकड़ा और नि: शुल्क अतिरिक्त स्मृति ट्रिम करने के लिए है, यह एक सभ्य हो सकता है बड़ी वस्तुओं के साथ स्मृति की मात्रा। – OneOfOne

+0

@OneOfOne सच है, यह निर्भर करता है कि क्या आप गति या स्मृति के लिए अनुकूलित कर रहे हैं। मैं वास्तव में सिर्फ एक नया टुकड़ा बनाउंगा और सब कुछ अपरिवर्तनीय रखूंगा, जब तक कि यह स्मृति का एक बड़ा हिस्सा न हो। –

+0

सच है, मेरा मतलब यह है कि http://play.golang.org/p/FgeuFdr3-v – OneOfOne

1

आपको यहां पॉइंटर का उपयोग करना होगा। यदि आप * xs को जोड़ना पसंद नहीं करते हैं, जहां सभी ऑपरेशन करने के लिए केवल एक temp चर का उपयोग करें, तो उसे वापस सेट करें। यहां कोड http://play.golang.org/p/eAFkV3Lwh6

1

आपका कोड लगभग सही था।

पहली बग यह है कि जब आप कोई तत्व हटा रहे हैं तो आपको i++ करने से बचने की आवश्यकता है, अन्यथा i++ अगले, अपठित तत्व पर छोड़ देता है। यही कारण है कि मैंने इसे else खंड में रखा है।

दूसरा बग कि xsFilter समारोह की एक स्थानीय चर रहा है है, इसलिए यदि आप बदलना क्या यह करने के लिए (xs = ... के साथ) बताते हैं कि main अंदर करने के लिए क्या a अंक नहीं बदलता है। आप इसे इस मुद्दे को एक पॉइंटर (*xs अन्य लोगों द्वारा पोस्ट किए गए) या नए फ़िल्टर किए गए टुकड़े को वापस कर कर हल कर सकते हैं, जैसा कि मैंने नीचे किया है।

package main 

import "fmt" 

type Ints []int 

func (xs Ints) Filtered() Ints { 
    for i := 0; i < len(xs); { 
     if xs[i]%2 == 0 { 
      xs = append(xs[:i], xs[i+1:]...) 
     } else { 
      i++ 
     } 
    } 
    return xs 
} 

func main() { 
    a := Ints([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 
    b := a.Filtered() 
    fmt.Println(b) 
} 

http://play.golang.org/p/Nre7w4KQ78

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