Да, я думаю, вы должны реорганизовать этот код, а не просто сделать его более компактным, но лучше выразить теоретико-множественный характер операций, которые вы выполняете. Обе функции задают вопрос о пересечении e.components
и components
.
Что вы, по сути говоря, с HasComponent
—, который, вероятно, должен быть назван HasAllComponents
— является то, что пересечение e.components
и components
равно components
. Другими словами, размер пересечения совпадает с размером components
.
Что касается HasAnyComponent
, то вы говорите, что размер пересечения по крайней мере один.
Обе функции могут быть выражены сжато путем тестирования размер пересечения, который вы можете получить, скажем, функцию, которая имеет эту подпись:
func (e *entity) CountComponents(components ...Component) int
Однако, исходный код имеет логику короткого замыкания который перестает смотреть на дополнительные компоненты, как только он знает ответ. Вы можете включить такое короткое замыкание цикла в функции с этой подписью:
func (e *entity) HasMinimumComponents(minimum int, components ...Component) bool
В цикле увеличиваем на count
переменную всякий раз, когда e.components[c.Type()] != nil
. Возврат true
как только count >= minimum
.
Теперь вы можете эффективно реализовать 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. –