gpt4 book ai didi

Golang 中的 map 集

转载 作者:IT王子 更新时间:2023-10-29 01:27:55 34 4
gpt4 key购买 nike

如果我有这样的结构:

type Foo struct {
title string
Tags map[string]string
}

如何维护一组独特的此类结构?据我了解,尽管结构相等是一回事,但映射相等却不是。这意味着我无法比较我的上述结构。因此我不能只执行 map as set pattern .

我能想到的两个可能可行的选项是:将标签转换为排序的 [][]stringuse reflect.Deepequal .谁有更好的主意?

最佳答案

有几种实现方法。 James Henstridge 实际上有一个好主意,我试图实现它。如果没有我自己的哈希算法,它一开始就使用 map 的性能很差。

我解决这个问题的方法是只保留一个结构数组,然后在插入它们时删除所有重复项。

package structset

type Foo struct {
title string
Tags map[string]string
}

func (f Foo) Equals(f2 Foo) bool {
if f.title != f2.title {
return false
}

if len(f.Tags) != len(f2.Tags) {
return false
}

for k, v := range f.Tags {
if w, ok := f2.Tags[k]; !ok || v != w {
return false
}
}

return true
}

type FooSet []Foo

func (this FooSet) Add(value Foo) {
if !this.Contains(value) {
this = append(this, value)
}
}

func (this FooSet) Length() int {
return len(this)
}

func (this FooSet) Contains(f Foo) bool {
for _, v := range this {
if v.Equals(f) {
return true
}
}
return false
}

func NewSet() FooSet {
return FooSet(make([]Foo, 0, 100))
}

我在我的 i7-3770K Windows 机器上对此进行了基准测试并得到:

BenchmarkSmallSetWithFewCollisions         50000             46615 ns/op
BenchmarkSmallSetWithMoreCollisions 50000 46575 ns/op
BenchmarkSmallSetWithManyCollisions 50000 46605 ns/op
BenchmarkMediumSetWithFewCollisions 1000 2335296 ns/op
BenchmarkMediumSetWithMoreCollisions 1000 2352298 ns/op
BenchmarkMediumSetWithManyCollisions 1000 2336796 ns/op
BenchmarkLargeSetWithFewCollisions 50 46805944 ns/op
BenchmarkLargeSetWithMoreCollisions 50 47376016 ns/op
BenchmarkLargeSetWithManyCollisions 50 46815946 ns/op

为了获得极少量的性能,您可以先将所有数据插入数组,然后再删除所有重复数据。

删除重复代码是:

func (this FooSet) RemoveDuplicates() {
length := len(this) - 1
for i := 0; i < length; i++ {
for j := i + 1; j <= length; j++ {
if this[i].Equals(this[j]) {
this[j] = this[length]
this = this[0:length]
length--
j--
}
}
}
}

这方面的基准是:

BenchmarkSmallSetWithFewCollisions         50000             45245 ns/op
BenchmarkSmallSetWithMoreCollisions 50000 45615 ns/op
BenchmarkSmallSetWithManyCollisions 50000 45555 ns/op
BenchmarkMediumSetWithFewCollisions 1000 2294791 ns/op
BenchmarkMediumSetWithMoreCollisions 1000 2309293 ns/op
BenchmarkMediumSetWithManyCollisions 1000 2286290 ns/op
BenchmarkLargeSetWithFewCollisions 50 46235870 ns/op
BenchmarkLargeSetWithMoreCollisions 50 46515906 ns/op
BenchmarkLargeSetWithManyCollisions 50 45865824 ns/op

这里是将 Foo 分配给 map[string]Foo 的基准。

BenchmarkSmallSetWithFewCollisions         50000             65718 ns/op
BenchmarkSmallSetWithMoreCollisions 50000 64238 ns/op
BenchmarkSmallSetWithManyCollisions 50000 55016 ns/op
BenchmarkMediumSetWithFewCollisions 500 3429435 ns/op
BenchmarkMediumSetWithMoreCollisions 500 3117395 ns/op
BenchmarkMediumSetWithManyCollisions 1000 2826858 ns/op
BenchmarkLargeSetWithFewCollisions 20 82635495 ns/op
BenchmarkLargeSetWithMoreCollisions 20 85285830 ns/op
BenchmarkLargeSetWithManyCollisions 20 73659350 ns/op

在我看来,即使 map 是可散列的,它的性能仍然不会很好。

关于Golang 中的 map 集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20691540/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com