我一直在研究一个问题,我想我可以用pokemon设置来演示它。我正在读取一个文件,解析该文件并从它们创建对象/结构。这通常不是一个问题,除了现在我需要实现接口,如继承特性。我不希望那里有重复的技能,所以我想我可以用一张地图来复制一个集合的数据结构。然而,在递归parsePokemonFile函数的传递阶段(请参阅implementsComponent情况),我似乎正在失去映射中的值。
我正在使用这样的输入:
4个档案
拉塔塔:
name=Ratatta
skills=Tackle:normal,Scratch:normal牛头龙:
name=Bulbosaur
implements=Ratatta
skills=VineWhip:leaf奥迪什:
name=Oddish
implements=Ratatatt
skills=Acid:poison维诺索:
name=Venosaur
implements=bulbosaur,oddish我期望下面代码的输出如下所示
Begin!
{Venosaur [{VineWhip leaf} {Acid poison} {Tackle normal} {Scratch normal}]}但我却得到了
Begin!
{Venosaur [{VineWhip leaf} {Acid poison}]}我做错了什么?这会是逻辑上的错误吗?或者,我是否在假设地图中包含我不该拥有的值?
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// In order to create a set of pokemon abilities and for ease of creation and lack of space being taken up
// We create an interfacer capability that imports the skills and attacks from pokemon of their previous evolution
// This reduces the amount of typing of skills we have to do.
// Algorithm is simple. Look for the name "implements=x" and then add x into set.
// Unfortunately it appears that the set is dropping values on transitive implements interfaces
func main() {
fmt.Println("Begin!")
dex, err := parsePokemonFile("Venosaur")
if err != nil {
fmt.Printf("Got error: %v\n", err)
}
fmt.Printf("%v\n", dex)
}
type pokemon struct {
Name string
Skills []skill
}
type skill struct {
SkillName string
Type string
}
func parsePokemonFile(filename string) (pokemon, error) {
file, err := os.Open(filename)
if err != nil {
return pokemon{}, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
var builtPokemon pokemon
for scanner.Scan() {
component, returned := parseLine(scanner.Text())
switch component {
case nameComponent:
builtPokemon.Name = returned
case skillsComponent:
skillsStrings := strings.Split(returned, ",")
var skillsArr []skill
// split skills and add them into pokemon skillset
for _, skillStr := range skillsStrings {
skillPair := strings.Split(skillStr, ":")
skillsArr = append(skillsArr, skill{SkillName: skillPair[0], Type: skillPair[1]})
}
builtPokemon.Skills = append(builtPokemon.Skills, skillsArr...)
case implementsComponent:
implementsArr := strings.Split(returned, ",")
// create set to remove duplicates
skillsSet := make(map[*skill]bool)
for _, val := range implementsArr {
// recursively call the pokemon files and get full pokemon
implementedPokemon, err := parsePokemonFile(val)
if err != nil {
return pokemon{}, err
}
// sieve out the skills into a set
for _, skill := range implementedPokemon.Skills {
skillsSet[&skill] = true
}
}
// append final set into the currently being built pokemon
for x := range skillsSet {
builtPokemon.Skills = append(builtPokemon.Skills, *x)
}
}
}
return builtPokemon, nil
}
type component int
// components to denote where to put our strings when it comes time to assemble what we've parsed
const (
nameComponent component = iota
implementsComponent
skillsComponent
)
func parseLine(line string) (component, string) {
arr := strings.Split(line, "=")
switch arr[0] {
case "name":
return nameComponent, arr[1]
case "implements":
return implementsComponent, arr[1]
case "skills":
return skillsComponent, arr[1]
default:
panic("Invalid field found")
}
}发布于 2019-03-20 18:31:40
这与Golang地图删除任何值无关。
问题是,您使用的是技能指针的地图,而不是技能。指向相同技能内容的两个指针可能不同。
skillsSet := make(map[*skill]bool)
如果您将此更改为map[skill]bool,则此操作应该有效。你可以试试!
https://stackoverflow.com/questions/55266979
复制相似问题