2013-06-29 52 views
2

我在閱讀清單中有一小段文章。每篇文章都有屬性「FeedURL」,其中包含文章來源Feed的URL。當我從訂閱源取消訂閱時,我希望能夠刪除包含該訂閱源網址的每篇文章。如何修改for循環中的切片?

type Article struct { 
    FeedURL string 
    URL  string // should be unique 
    // ... more data 
} 

func unsubscribe(articleList []Article, url string) []Article { 
    // how do I remove every Article from articleList that contains url? 
} 

func main() { 
    myArticleList := []Article{ 
     Article{"http://blog.golang.org/feed.atom", "http://blog.golang.org/race-detector"}, 
     Article{"http://planet.python.org/rss20.xml", "http://archlinux.me/dusty/2013/06/29/creating-an-application-in-kivy-part-3/"}, 
     Article{"http://planet.python.org/rss20.xml", "http://feedproxy.google.com/~r/cubicweborg/~3/BncbP-ap0n0/2957378"}, 
     // ... much more examples 
    } 

    myArticleList = unsubscribe(myArticleList, "http://planet.python.org/rss20.xml") 

    fmt.Printf("%+v", myArticleList) 
} 

解決此問題的有效方法是什麼?

起初,我的代碼看起來像這樣取消:

func unsubscribe(articleList []Article, url string) []Article { 
    for _, article := range articleList { 
     if article.FeedURL == url { 
      articleList = append(articleList[:i], articleList[i+1:]...) 
     } 
    } 
    return articleList 
} 

但後來我意識到,這將改變切片,使for循環不可預知的。

什麼是實現這一目標的有效方法?

+1

Re:_「但後來我意識到這會改變切片,並使for循環變得不可預知。」_循環_is_完全可預測。在執行範圍語句之前,範圍表達式僅計算一次。 – zzzz

回答

5

爲了提高效率:

  • 使用指針一片文章,那麼我們將指針移動到 結構,而不是結構值。
  • 如果列表中的文章順序不重要,請使用 無序算法;它減少指針移動。否則,請使用 排序算法。無論如何,最小化指針移動。
  • 不要將懸掛指針留在列表末尾。垃圾 收集者會認爲他們仍在使用;它看片 容量不是片長。
  • 最小化內存分配。

例如,

package main 

import "fmt" 

type Article struct { 
    FeedURL string 
    URL  string // should be unique 
    // ... more data 
} 

// Remove every Article from an articleList that contains url without preserving order. 
func unsubscribeUnordered(a []*Article, url string) []*Article { 
    for i := 0; i < len(a); i++ { 
     if a[i].FeedURL == url { 
      a[len(a)-1], a[i], a = nil, a[len(a)-1], a[:len(a)-1] 
      i-- 
     } 
    } 
    return a 
} 

// Remove every Article from an articleList that contains url while preserving order. 
func unsubscribeOrdered(a []*Article, url string) []*Article { 
    j := 0 
    for i := 0; i < len(a); i++ { 
     if a[i].FeedURL == url { 
      continue 
     } 
     if i != j { 
      a[j] = a[i] 
     } 
     j++ 
    } 
    for k := j; k < len(a); k++ { 
     a[k] = nil 
    } 
    return a[:j] 
} 

func NewArticleList() []*Article { 
    return []*Article{ 
     &Article{"http://blog.golang.org/feed.atom", "http://blog.golang.org/race-detector"}, 
     &Article{"http://planet.python.org/rss20.xml", "http://archlinux.me/dusty/2013/06/29/creating-an-application-in-kivy-part-3/"}, 
     &Article{"http://planet.python.org/rss20.xml", "http://feedproxy.google.com/~r/cubicweborg/~3/BncbP-ap0n0/2957378"}, 
     // ... much more examples 
    } 
} 

func PrintArticleList(a []*Article) { 
    fmt.Print("[") 
    for _, e := range a { 
     fmt.Printf("%+v", *e) 
    } 
    fmt.Println("]") 
} 

func main() { 
    PrintArticleList(NewArticleList()) 
    ao := unsubscribeOrdered(NewArticleList(), "http://planet.python.org/rss20.xml") 
    PrintArticleList(ao) 
    auo := unsubscribeUnordered(NewArticleList(), "http://planet.python.org/rss20.xml") 
    PrintArticleList(auo) 
} 

輸出:

[{FeedURL:http://blog.golang.org/feed.atom URL:http://blog.golang.org/race-detector}{FeedURL:http://planet.python.org/rss20.xml URL:http://archlinux.me/dusty/2013/06/29/creating-an-application-in-kivy-part-3/}{FeedURL:http://planet.python.org/rss20.xml URL:http://feedproxy.google.com/~r/cubicweborg/~3/BncbP-ap0n0/2957378}] 

[{FeedURL:http://blog.golang.org/feed.atom URL:http://blog.golang.org/race-detector}] 
[{FeedURL:http://blog.golang.org/feed.atom URL:http://blog.golang.org/race-detector}] 
0

PeterSO的答案是能夠完成任務,並與工作效率。

不過,我可能會用這樣的

func unsubscribe(articleList []Article, url string) (filtered []Article) { 
    filtered = articleList[:0] // optional. reuses already-allocated memory. 
    for _, article := range articleList { 
     if article.FeedURL != url { 
      filtered = append(filtered, article) 
     } 
    } 
    return 
} 

只需要大約兩秒鐘的閱讀和理解簡單的東西去了。

這個想法也可以很好地用指向文章的指針,就像PeterSO所說的,如果你的Article結構很大,那可能是一件好事。

+2

發佈解答工作。他們至少應該編譯。你仍然有第2行中的拼寫錯誤。 – peterSO

+0

我確信...謝謝。 – mac01021