如何解析任意长度的文件?

我有一个文本文件,我想用这样的记录来解析:


===================

name: John Doe

Education: High School Diploma

Education: Bachelor's Degree

Education: Sun Java Certified Programmer

Age: 29

===================

name: Bob Bear

Education: High School Diploma

Age: 18

===================

name: Jane Doe

Education: High School Diploma

Education: Bachelor's Degree

Education: Master's Degree

Education: AWS Certified Solution Architect Professional

Age: 25

如您所见,fields此类文本文件中的是固定的,但其中一些重复了任意多次。记录由固定长度的====定界符分隔。


我将如何为此类问题编写解析逻辑?我想使用switch它来读取行的开头,但是处理多个重复字段的逻辑使我感到困惑。


慕工程0101907
浏览 215回答 2
2回答

白猪掌柜的

编辑:添加为什么我只是发布一个程序作为答案的说明。我正在提出一个非常简单的实现,以解析您在问题中给出的文本。您接受了数学答案,这是可以的。不过,我想在他的回答中添加一些反论点。基本上,该答案中的伪代码是我的答案中的代码的不可编译版本,因此我们同意该解决方案。我不同意的是过度设计的谈话。我每天都要处理思想过度的人编写的代码。我敦促您不要考虑模式,内存和时间限制,否则将来谁可能想要这些。访客模式?那只是在解析编程语言时非常有用的东西,不要试图从这个问题构造一个用例。访客模式用于遍历其中包含不同类型事物的树。在这里,我们列出了所有相同的东西,而不是一棵树。内存和时间限制?您正在解析5 GB的文本吗?那么这可能是一个真正的问题。但是,即使您这样做,也要始终先写最简单的东西。足够了。在我的整个职业生涯中,我只需要每年使用一次简单数组之外的其他东西或应用复杂算法。仍然到处都可以看到无缘无故地使用复杂数据结构和算法的代码。这使更改变得复杂,容易出错,有时最终会使速度变慢!不要使用可观察的列表抽象,只要它的内容发生更改,它就会通知所有观察者-但是,让我们添加一个更新锁定和解锁,以便我们可以控制何时不通知所有人...否!不要沿着那条路线走。用一片。做你的逻辑。使所有内容从上到下都易于阅读。我不想从A跳到B再跳到C,追逐接口,跟随吸气剂最终找到的不是具体的数据类型,而是另一个接口。那不是要走的路。这就是为什么我的代码不导出任何内容的原因,它是一个独立的,可运行的示例,是针对您的具体问题的具体解决方案。您可以阅读它,很容易理解。它没有被大量评论,因为它不需要被评论。这三个评论不是说明会发生什么,而是说明为什么会发生。其他所有内容都可以从代码本身中看出。我故意留下有关潜在错误的注释。您知道自己拥有哪种数据,那里没有行会触发此错误。不要编写代码来处理不可能发生的事情。如果将来有人在冒号后添加一行没有文本的行(请记住,没有人会这样做,不用担心),这将引发恐慌,将您指向此行,然后添加另外的if或某物,你完成了。我要延伸的主要观点是:只写解决当前问题所需的内容。除此之外的所有内容都使您的程序难以阅读和更改,它将未经测试且不必要。话虽如此,这是我的原始答案:https://play.golang.org/p/T6c51jSM5nrpackage mainimport (    "fmt"    "strconv"    "strings")func main() {    type item struct {        name       string        educations []string        age        int    }    var items []item    var current item    finishItem := func() {        if current.name != "" { // handle the first ever separator            items = append(items, current)        }        current = item{}    }    lines := strings.Split(code, "\n")    for _, line := range lines {        if line == separator {            finishItem()        } else {            colon := strings.Index(line, ":")            if colon != -1 {                id := line[:colon]                value := line[colon+2:] // note potential bug if text has nothing after ':'                switch id {                case "name":                    current.name = value                case "Education":                    current.educations = append(current.educations, value)                case "Age":                    age, err := strconv.Atoi(value)                    if err == nil {                        current.age = age                    }                }            }        }    }    finishItem() // in case there was no separator at the end    for _, item := range items {        fmt.Printf("%s, %d years old, has educations:\n", item.name, item.age)        for _, e := range item.educations {            fmt.Printf("\t%s\n", e)        }    }}const separator = "==================="const code = `===================name: John DoeEducation: High School DiplomaEducation: Bachelor's DegreeEducation: Sun Java Certified ProgrammerAge: 29===================name: Bob BearEducation: High School DiplomaAge: 18===================name: Jane DoeEducation: High School DiplomaEducation: Bachelor's DegreeEducation: Master's DegreeEducation: AWS Certified Solution Architect ProfessionalAge: 25`
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go