【问题标题】:not able to search for an item in a slice of structs无法在一片结构中搜索项目
【发布时间】:2013-09-04 10:38:18
【问题描述】:

在这个上拉我的头发。任何帮助将不胜感激。我创建了一个名为 Person 的结构,以及一个名为 PersonList 的自定义切片类型,其中包含 *Person。我能够对切片进行填充和排序,但是在搜索切片时,我得到了奇怪的结果:搜索能够找到一些项目,但不能找到其他项目。

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,但是找不到其他的。

有什么想法吗?非常感谢!

【问题讨论】:

    标签: sorting search go slice


    【解决方案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 方法。

    Package sort

    func Search

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

    搜索使用二分搜索来查找并返回最小索引 i [0, n) 其中 f(i) 为真,假设在 [0, n) 范围内,f(i) == true 意味着 f(i+1) == true。也就是说,搜索要求 f 对于输入范围 [0, n) 的某些(可能为空)前缀为假,并且 然后对于(可能为空的)余数为真;搜索返回第一个 真实指数。如果没有这样的索引,Search 返回 n。 (注意 “未找到”返回值不是 -1,例如, 字符串。索引)。搜索仅对 [0, n) 范围内的 i 调用 f(i)。

    Search 的一个常见用途是在 a 中查找值 x 的索引 i 排序的、可索引的数据结构,例如数组或切片。在这个 在这种情况下,参数 f,通常是一个闭包,捕获的值是 搜索,以及如何对数据结构进行索引和排序。

    例如,给定一个按升序排序的切片数据,调用 Search(len(data), func(i int) bool { return data[i] >= 23 }) 返回 最小索引 i 使得 data[i] >= 23。如果调用者想要 查找 23 是否在切片中,必须测试 data[i] == 23 分开。

    搜索按降序排序的数据将使用 = 运算符。

    【讨论】:

    • 感谢彼得为我指明了正确的方向!你刚刚度过了我的周末!是的,我确实阅读了 go 文档,但我承认我有点慢,并且仍在学习细微差别。再次感谢!
    猜你喜欢
    • 2018-05-10
    • 2019-05-07
    • 1970-01-01
    • 2019-12-06
    • 2023-01-15
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    相关资源
    最近更新 更多