为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕工程0101907 2021-04-10 19:19:26
我有一个文本文件,我想用这样的记录来解析:===================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如您所见,fields此类文本文件中的是固定的,但其中一些重复了任意多次。记录由固定长度的====定界符分隔。我将如何为此类问题编写解析逻辑?我想使用switch它来读取行的开头,但是处理多个重复字段的逻辑使我感到困惑。
查看完整描述

2 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

编辑:添加为什么我只是发布一个程序作为答案的说明。


我正在提出一个非常简单的实现,以解析您在问题中给出的文本。您接受了数学答案,这是可以的。不过,我想在他的回答中添加一些反论点。基本上,该答案中的伪代码是我的答案中的代码的不可编译版本,因此我们同意该解决方案。


我不同意的是过度设计的谈话。我每天都要处理思想过度的人编写的代码。我敦促您不要考虑模式,内存和时间限制,否则将来谁可能想要这些。


访客模式?那只是在解析编程语言时非常有用的东西,不要试图从这个问题构造一个用例。访客模式用于遍历其中包含不同类型事物的树。在这里,我们列出了所有相同的东西,而不是一棵树。


内存和时间限制?您正在解析5 GB的文本吗?那么这可能是一个真正的问题。但是,即使您这样做,也要始终先写最简单的东西。足够了。在我的整个职业生涯中,我只需要每年使用一次简单数组之外的其他东西或应用复杂算法。仍然到处都可以看到无缘无故地使用复杂数据结构和算法的代码。这使更改变得复杂,容易出错,有时最终会使速度变慢!不要使用可观察的列表抽象,只要它的内容发生更改,它就会通知所有观察者-但是,让我们添加一个更新锁定和解锁,以便我们可以控制何时不通知所有人...否!不要沿着那条路线走。用一片。做你的逻辑。使所有内容从上到下都易于阅读。我不想从A跳到B再跳到C,追逐接口,跟随吸气剂最终找到的不是具体的数据类型,而是另一个接口。那不是要走的路。


这就是为什么我的代码不导出任何内容的原因,它是一个独立的,可运行的示例,是针对您的具体问题的具体解决方案。您可以阅读它,很容易理解。它没有被大量评论,因为它不需要被评论。这三个评论不是说明会发生什么,而是说明为什么会发生。其他所有内容都可以从代码本身中看出。我故意留下有关潜在错误的注释。您知道自己拥有哪种数据,那里没有行会触发此错误。不要编写代码来处理不可能发生的事情。如果将来有人在冒号后添加一行没有文本的行(请记住,没有人会这样做,不用担心),这将引发恐慌,将您指向此行,然后添加另外的if或某物,你完成了。


我要延伸的主要观点是:只写解决当前问题所需的内容。除此之外的所有内容都使您的程序难以阅读和更改,它将未经测试且不必要。


话虽如此,这是我的原始答案:


https://play.golang.org/p/T6c51jSM5nr


package main


import (

    "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 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`


查看完整回答
反对 回复 2021-04-19
  • 2 回答
  • 0 关注
  • 214 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信