如何在 Go 中組合分揀機?例如,首先我需要按評論數排序,但如果評論數為空,我需要按字母順序排序。
這是我嘗試過的。
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := make([]*Article, 0)
topArticlesSlice = append(topArticlesSlice, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
var sortedByNumComments, areNumCommentsEquals, sortedByName bool
if topArticlesSlice[i].NumComments != nil && topArticlesSlice[j].NumComments != nil {
areNumCommentsEquals = *topArticlesSlice[i].NumComments == *topArticlesSlice[j].NumComments
sortedByNumComments = *topArticlesSlice[i].NumComments > *topArticlesSlice[j].NumComments
}
if areNumCommentsEquals {
if topArticlesSlice[i].Title != nil && topArticlesSlice[j].Title != nil {
sortedByName = *topArticlesSlice[i].Title == *topArticlesSlice[j].Title
return sortedByName
} else if topArticlesSlice[i].StoryTitle != nil && topArticlesSlice[j].StoryTitle != nil {
sortedByName = *topArticlesSlice[i].StoryTitle == *topArticlesSlice[j].StoryTitle
return sortedByName
}
return false
}
return sortedByNumComments
})
return topArticlesSlice
}
我的結構(https://go.dev/play/p/27j-sFKaG2M)
type ArticleResponse struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
TotalPages int `json:"total_pages"`
Articles []*Article `json:"data"`
}
type Article struct {
Title *string `json:"title"`
URL *string `json:"url"`
Author string `json:"author"`
NumComments *int `json:"num_comments"`
StoryID interface{} `json:"story_id"`
StoryTitle *string `json:"story_title"`
StoryURL *string `json:"story_url"`
ParentID *int `json:"parent_id"`
CreatedAt int `json:"created_at"`
}
uj5u.com熱心網友回復:
您的比較功能太復雜了。您需要將其重構為更簡單更直接的部分。
而且,您還沒有定義您的Article型別是什么樣的,因此,出于示例的目的,我將這樣定義它:
type Article struct {
NumComments *int
Title *string
}
您的基本要求是您要先按評論數排序,然后(如果評論數為零)按標題字母順序排序,對嗎?
從您的原始代碼看來,
NumComments是一個指向 int (*int) 的指標,并且Title是指向字串 (*string)的指標
這意味著每次比較都有四種情況需要處理:
| X | 是 | 行動 |
|---|---|---|
| 非零 | 非零 | 比較 x 和 y(根據它們的基礎型別) |
| 非零 | 零 | nil 與非 nil 相比如何?(實作細節) |
| 零 | 非零 | nil 與非 nil 相比如何?(實作細節) |
| 零 | 零 | 為了整理的目的,兩個 nil 比較相等 |
出于本練習的目的,我將宣告 nil 相對于 non-nil 排序為高(但 nil 相對于 non-nil 排序為低同樣有效。一種實作選擇)。
比較 2 個*int值很容易:
func compareIntPtr(x *int, y *int) int {
var cc int
switch {
case x != nil && y != nil: cc = sign(*x - *y)
case x == nil && y == nil: cc = 0
case x == nil && y != nil: cc = 1
case x != nil && y == nil: cc = -1
}
return cc
}
func sign(n int) int {
var sign int
switch {
case n < 0: sign = -1
case n > 0: sign = 1
default: sign = 0
}
return sign
}
正如比較兩個*string值:
import "strings"
.
.
.
func compareStringPtr(x *string, y *string) int {
var cc int
switch {
case x != nil && y != nil: cc = strings.Compare(*x, *y)
case x == nil && y == nil: cc = 0
case x == nil && y != nil: cc = 1
case x != nil && y == nil: cc = -1
}
return cc
}
一旦你有了這些原語,排序的比較函式就更簡單了:
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := make([]*Article, 0)
topArticlesSlice = append(topArticlesSlice, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
x := *topArticlesSlice[i]
y := *topArticlesSlice[j]
// compare numbers of comments
cc := compareIntPtr(x.NumComments, y.NumComments)
// if equal, compare the titles
if cc == 0 {
cc = compareStringPtr(x.Title, y.Title)
}
// return `true` if `x` collates less than `y`, otherwise `false`
return cc < 0
})
return topArticlesSlice
}
uj5u.com熱心網友回復:
package main
import (
"fmt"
"sort"
)
type Article struct {
Title string
NumComments int
}
func main() {
a1 := Article{"Dog", 3}
a2 := Article{"Tiger", 0}
a3 := Article{"Cat", 4}
a4 := Article{"Fish", 0}
a5 := Article{"Whale", 8}
articles := []Article{a1, a2, a3, a4, a5}
sort.Slice(articles, func(i, j int) bool {
if articles[i].NumComments == 0 && articles[j].NumComments == 0 {
return articles[i].Title < articles[j].Title
} else {
return articles[i].NumComments < articles[j].NumComments
}
})
fmt.Printf("articles: %v\n", articles)
}
您的帖子中缺少某些型別定義。我舉了一個簡單的支柱例子。我想這就是您可能正在尋找的東西?
uj5u.com熱心網友回復:
假設我正確理解了您的要求,您可以使用以下內容:
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := append([]*Article{}, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
if topArticlesSlice[i].NumComments != nil && topArticlesSlice[j].NumComments != nil &&
*topArticlesSlice[i].NumComments != *topArticlesSlice[j].NumComments {
return *topArticlesSlice[i].NumComments < *topArticlesSlice[j].NumComments
}
if topArticlesSlice[i].Title != nil && topArticlesSlice[j].Title != nil &&
*topArticlesSlice[i].Title != *topArticlesSlice[j].Title {
return *topArticlesSlice[i].Title < *topArticlesSlice[j].Title
} else if topArticlesSlice[i].StoryTitle != nil && topArticlesSlice[j].StoryTitle != nil {
return *topArticlesSlice[i].StoryTitle < *topArticlesSlice[j].StoryTitle
}
return false
})
return topArticlesSlice
}
在操場上試試這個。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/438852.html
