gpt4 book ai didi

go - 如何在 Go 中抽象出相同类型的循环细节?

转载 作者:IT王子 更新时间:2023-10-29 01:48:13 28 4
gpt4 key购买 nike

我有以下类型:

type entity struct {
components []Component
}

func NewEntity(componentsLength ComponentType) Entity {
return &entity{
components: make([]Component, componentsLength),
}
}

在编码时,我注意到以下重复模式:

func (e *entity) HasComponent(components ...Component) bool {
for _, c := range components {
if e.components[c.Type()] == nil {
return false
}
}
return true
}

func (e *entity) HasAnyComponent(components ...Component) bool {
for _, c := range components {
if e.components[c.Type()] != nil {
return true
}
}
return false
}

当你为不同的类型编写相似的函数时,Go 似乎可以接受大量重复的代码。但是,在这种情况下,类型是相同的。我仍然无法重构代码以推广 for 循环和 if 语句的使用。

我如何重构这些函数,以便列表处理是通用的,但 bool 运算符和值被抽象出来?我应该吗?

最佳答案

是的,我认为您应该重构此代码,不仅是为了使其更紧凑,而且是为了更好地表达您正在执行的操作的集合论性质。这两个函数都在询问有关 e.componentscomponents 的交集的问题。

HasComponent 本质上是在说什么——它应该叫做 HasAllComponents——是 e.componentscomponents 等于 components。换句话说,交集的大小与 components 的大小相同。

至于HasAnyComponent,你说的是交集的大小至少为1。

这两个函数都可以通过测试交集的大小来简洁地表达,您可以通过具有以下签名的函数获得:

func (e *entity) CountComponents(components ...Component) int

但是,您的原始代码具有短路逻辑,一旦知道答案就会停止查看其他组件。您可以将这样的短路循环合并到具有此签名的函数中:

func (e *entity) HasMinimumComponents(minimum int, components ...Component) bool

在循环中,每当 e.components[c.Type()] != nil 时递增一个 count 变量。一旦 count >= minimum 就返回 true

现在您可以使用单行主体高效地实现 HasAllComponents:

return entity.HasMinimumComponents(len(components), components...)

HasAnyComponent 的主体变为:

return entity.HasMinimumComponents(1, components...)

下面是一个用略有不同的数据类型实现这个想法的程序。我定义了一种更抽象的 Entity,它包含一个 map[int]bool。将这个想法应用到您自己的程序中应该没有问题。

package main

import (
"fmt"
)

type Entity struct {
ValueMap map[int]bool
}

func MakeEntity(values ...int) *Entity {
entity := Entity{map[int]bool{}}
for _, value := range values {
entity.ValueMap[value] = true
}
return &entity
}

func (entity *Entity) HasMinimumValues(minimum int, values ...int) bool {
count := 0
if minimum == 0 {
return true
}
for _, value := range values {
if entity.ValueMap[value] {
count++
if count >= minimum {
return true
}
}
}
return false
}

func (entity *Entity) HasAllValues(values ...int) bool {
return entity.HasMinimumValues(len(values), values...)
}

func (entity *Entity) HasAnyValue(values ...int) bool {
return entity.HasMinimumValues(1, values...)
}

func main() {
entity := MakeEntity(1, 3, 5, 7, 9)
fmt.Printf("%t\n", entity.HasAllValues(3, 9))
fmt.Printf("%t\n", entity.HasAllValues(3, 9, 12))
fmt.Printf("%t\n", entity.HasAnyValue(9, 12, 15))
fmt.Printf("%t\n", entity.HasAnyValue(12, 15))
}

关于go - 如何在 Go 中抽象出相同类型的循环细节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30097775/

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