1

これで髪を伸ばします。どんな助けでも大歓迎です。Person という構造体と、*Person を保持する PersonList というカスタム スライス タイプを作成しました。スライスにデータを入力して並べ替えることができますが、スライスを検索すると奇妙な結果が得られます。

type Person struct {
    id   int
    name string
}

type PersonList []*Person

func (pl *PersonList) Add(p *Person) {
    *pl = append(*pl, p)
}

func (pl PersonList) Search(id int) int {
    f := func(i int) bool { return pl[i].id == id }
    return sort.Search(len(pl), f)
}

func (pl PersonList) Sort() {
    sort.Sort(pl)
}

func (pl PersonList) IsSorted() bool {
    return sort.IsSorted(pl)
}

func (pl PersonList) Len() int {
    return len(pl)
}

func (pl PersonList) Swap(i, j int) {
    pl[i], pl[j] = pl[j], pl[i]
}

func (pl PersonList) Less(i, j int) bool {
    return pl[i].id < pl[j].id
}

func (p Person) String() string {
    return "id=" + strconv.Itoa(p.id) + " name=" + p.name + "\n"
}

func main() {
    plist := make(PersonList, 0)
    plist.Add(&Person{839, "Bob"})
    plist.Add(&Person{23, "Larry"})
    plist.Add(&Person{93420, "Jane"})
    plist.Add(&Person{3, "Sam"})
    plist.Add(&Person{7238, "Betty"})
    fmt.Printf("plist=%v\n", plist)
    plist.Sort()
    fmt.Printf("plist=%v\n", plist)
    fmt.Printf("3=%d\n", plist.Search(3))
    fmt.Printf("23=%d\n", plist.Search(23))
    fmt.Printf("839=%d\n", plist.Search(839))
    fmt.Printf("7238=%d\n", plist.Search(7238))
    fmt.Printf("93420=%d\n", plist.Search(93420))
}

出力は次のとおりです。

plist=[id=839 name=Bob
 id=23 name=Larry
 id=93420 name=Jane
 id=3 name=Sam
 id=7238 name=Betty
]
plist=[id=3 name=Sam
 id=23 name=Larry
 id=839 name=Bob
 id=7238 name=Betty
 id=93420 name=Jane
]
3=5
23=5
839=2
7238=5
93420=4

検索方法は、id の 839 と 93420 を見つけることができましたが、他のものを見つけることができませんでした。

何か案は?どうもありがとう!

4

1 に答える 1

1

例えば、

package main

import (
    "fmt"
    "sort"
    "strconv"
)

type Person struct {
    id   int
    name string
}

type PersonList []*Person

func (pl *PersonList) Add(p *Person) {
    *pl = append(*pl, p)
}

func (pl PersonList) Search(id int) int {
    f := func(i int) bool { return pl[i].id >= id }
    if i := sort.Search(len(pl), f); pl[i].id == id {
        return i
    }
    return -1
}

func (pl PersonList) Sort() {
    sort.Sort(pl)
}

func (pl PersonList) IsSorted() bool {
    return sort.IsSorted(pl)
}

func (pl PersonList) Len() int {
    return len(pl)
}

func (pl PersonList) Swap(i, j int) {
    pl[i], pl[j] = pl[j], pl[i]
}

func (pl PersonList) Less(i, j int) bool {
    return pl[i].id < pl[j].id
}

func (p Person) String() string {
    return "id=" + strconv.Itoa(p.id) + " name=" + p.name + "\n"
}

func main() {
    plist := make(PersonList, 0)
    plist.Add(&Person{839, "Bob"})
    plist.Add(&Person{23, "Larry"})
    plist.Add(&Person{93420, "Jane"})
    plist.Add(&Person{3, "Sam"})
    plist.Add(&Person{7238, "Betty"})
    fmt.Printf("plist=%v\n", plist)
    plist.Sort()
    fmt.Printf("plist=%v\n", plist)
    fmt.Printf("3=%d\n", plist.Search(3))
    fmt.Printf("23=%d\n", plist.Search(23))
    fmt.Printf("839=%d\n", plist.Search(839))
    fmt.Printf("7238=%d\n", plist.Search(7238))
    fmt.Printf("93420=%d\n", plist.Search(93420))
}

出力:

plist=[id=839 name=Bob
 id=23 name=Larry
 id=93420 name=Jane
 id=3 name=Sam
 id=7238 name=Betty
]
plist=[id=3 name=Sam
 id=23 name=Larry
 id=839 name=Bob
 id=7238 name=Betty
 id=93420 name=Jane
]
3=0
23=1
839=2
7238=3
93420=4

PersonList Search私はあなたの方法を修正しました。

パッケージソート

機能検索

func Search(n int, f func(int) bool) int

検索は二分探索を使用して、範囲 [0, n) で f(i) == true が f(i+ 1) == 真。つまり、検索では、入力範囲 [0, n) の一部の (空の可能性がある) プレフィックスに対して f が false であり、残りの (空の可能性がある) に対して true である必要があります。検索は、最初の真のインデックスを返します。そのようなインデックスがない場合、Search は n を返します。("not found" の戻り値は、strings.Index のように -1 ではないことに注意してください)。検索は、範囲 [0, n) の i に対してのみ f(i) を呼び出します。

Search の一般的な用途は、配列やスライスなどの並べ替えられたインデックス可能なデータ構造で、値 x のインデックス i を見つけることです。この場合、引数 f (通常はクロージャー) は、検索対象の値と、データ構造のインデックスと順序付けの方法をキャプチャします。

たとえば、昇順で並べ替えられたスライス データがある場合、Search(len(data), func(i int) bool { return data[i] >= 23 }) を呼び出すと、data[i] > を満たす最小のインデックス i が返されます。 = 23. 呼び出し元が 23 がスライスにあるかどうかを調べたい場合は、data[i] == 23 を個別にテストする必要があります。

降順でソートされたデータを検索するには、>= 演算子の代わりに <= 演算子を使用します。

于 2013-09-01T02:39:58.013 に答える