【问题标题】:Dividing up input txt wrong分割输入txt错误
【发布时间】:2016-11-17 11:18:52
【问题描述】:

我正在尝试编写一个程序,输入用户所述的两个 txt 文件,获取关键字文件并将其拆分为单词和值,然后获取推文文件,将其拆分为位置和推文/时间.

关键字文件示例(单行距 .txt 文件):

*爱,10

喜欢,5

最好,10

讨厌,1

哈哈,10

更好,10*

推文文件示例(注意这里只显示了四个,实际的 .txt 文件中实际上有几百行):

[41.298669629999999, -81.915329330000006] 6 2011-08-28 19:02:36 工作需要飞速发展......我很高兴看到 Spy Kids 4 和我的生活一样热爱...... ARREIC

[33.702900329999999, -117.95095704000001] 6 2011-08-28 19:03:13 今天将是我一生中最伟大的一天。受雇在我最好朋友的祖父母 50 周年纪念日拍照。 60位老人。呜呜呜。

[38.809954939999997, -77.125144050000003] 6 2011-08-28 19:07:05 我只是把我的生命放在5个手提箱里

[27.994195699999999, -82.569434900000005] 6 2011-08-28 19:08:02 @Miss_mariiix3 是我一生的挚爱

到目前为止,我的程序看起来像:

#prompt the user for the file name of keywords file
keywordsinputfile = input("Please input file name: ")
tweetsinputfile = input ("Please input tweets file name: ")

#try to open given input file
try:
    k=open(keywordsinputfile, "r")
except IOError:
    print ("{} file not found".format(keywordsinputfile))
try:
    t=open(tweetsinputfile, "r")
except IOError:
    print ("{} file not found".format(tweetsinputfile))
    exit()

def main ():   #main function
    kinputfile = open(keywordsinputfile, "r")         #Opens File for keywords
    tinputfile = open(tweetsinputfile, "r")           #Opens file for tweets
    HappyWords = {}
    HappyValues = {}
    for line in kinputfile:                           #splits keywords
        entries = line.split(",")
        hvwords = str(entries[0])
        hvalues = int(entries[1])
        HappyWords["keywords"] = hvwords           #stores Happiness keywords
        HappyValues["values"] = hvalues            #stores Happiness Values
    for line in tinputfile:
        twoparts = line.split("]")  #splits tweet file by ] creating a location and tweet parts, tweets are ignored for now
        startlocation = (twoparts[0])   #takes the first part (the locations)
    def testing(startlocation):
        for line in startlocation:     
            intlocation = line.split("[")      #then gets rid of the "[" at the beginning of the locations
            print (intlocation)
    testing(startlocation)

main()

我希望从中得到的是(对于无限多的行,实际文件包含的远远超过上面显示的四个)

41.298669629999999, -81.915329330000006
33.702900329999999, -117.95095704000001
38.809954939999997, -77.125144050000003
27.994195699999999, -82.569434900000005

我得到的是:

['', '']
['2']
['7']
['.']
['9']
['9']
['4']
['1']
['9']
['5']
['6']
['9']
['9']
['9']
['9']
['9']
['9']
['9']
['9']
[',']
[' ']
['-']
['8']
['2']
['.']
['5']
['6']
['9']
['4']
['3']
['4']
['9']
['0']
['0']
['0']
['0']
['0']
['0']
['0']
['5']

也就是说,它只处理 txt 文件的最后一行并将其单独拆分。

在此之后,我必须以这样一种方式存储它们,以便我可以将它们再次拆分为一个列表中的第一部分和另一个列表中的第二部分 (例如:

for line in locations:
    entries = line.split(",")
    latitude = intr(entries[0])
    longitude = int(entries[1])

提前致谢!

【问题讨论】:

  • 您在循环中一次又一次地覆盖HappyWords["keywords"] HappyValues["values"]。所以你只看到关键字文件的最后一行。
  • 感谢您的评论,我已解决此问题,但我尝试提取的代码部分根本不使用这些值。仍然有同样的错误。
  • 使用print()查看所有变量中的内容 - 这样您就可以找到出错的地方。

标签: python python-3.x pycharm


【解决方案1】:

您只需要添加一些跟踪 print 语句来显示正在发生的事情。我是这样做的:

for line in tinputfile:
    twoparts = line.split("]")  #splits tweet file by ] creating a location and tweet parts, tweets are ignored for now
    startlocation = (twoparts[0])   #takes the first part (the locations)
    print ("-----------")
    print ("twoparts", twoparts) 
    print ("startlocation", startlocation)
def testing(startlocation):
    for line in startlocation:     
        print ("line", line)
        intlocation = line.split("[")      #then gets rid of the "[" at the beginning of the locations
        print ("intlocation", intlocation)
testing(startlocation)

...并得到一个以:

开头的跟踪
-----------
twoparts ['[41.298669629999999, -81.915329330000006', " 6 2011-08-28 19:02:36 Work needs to fly by ... I'm so excited to see Spy Kids 4 with then love of my life ... ARREIC\n"]
startlocation [41.298669629999999, -81.915329330000006
-----------
twoparts ['[33.702900329999999, -117.95095704000001', " 6 2011-08-28 19:03:13 Today is going to be the greatest day of my life. Hired to take pictures at my best friend's gparents 50th anniversary. 60 old people. Woo.\n"]
startlocation [33.702900329999999, -117.95095704000001
-----------
twoparts ['[38.809954939999997, -77.125144050000003', ' 6 2011-08-28 19:07:05 I just put my life in like 5 suitcases\n']
startlocation [38.809954939999997, -77.125144050000003
-----------
twoparts ['[27.994195699999999, -82.569434900000005', ' 6 2011-08-28 19:08:02 @Miss_mariiix3 is the love of my life\n']
startlocation [27.994195699999999, -82.569434900000005
line [
intlocation ['', '']
line 2
intlocation ['2']
line 7

分析:

有两个基本问题:

  1. 您的处理语句 testing(startlocation) 在循环之外,因此它只使用最后一个输入行。
  2. 正如您在“twoparts”的输出中看到的那样,您想要的坐标仍然是 string 格式,而不是浮点数列表。您需要剥去支架并将它们分开。 然后将它们转换为浮点数。在当前形式中,当您遍历 intlocation 时,您会遍历字符串的字符,而不是遍历两个浮点数。

另外:为什么要在循环中定义函数?这重新定义了每次执行的功能。把它移到主程序之前;这是表现良好的功能的地方。 :-)


添加了关于第 2 点的信息:

让我们使用示例输入的最后一行单步执行您的代码。 从循环顶部开始 for tinputfile 中的行

twoparts = line.split("]")

twoparts 现在是一对元素,都是字符串:

['[27.994195699999999, -82.569434900000005',
 ' 6 2011-08-28 19:08:02 @Miss_mariiix3 is the love of my life\n']

然后将 startlocation 设置为第一个元素:

'[27.994195699999999, -82.569434900000005'

然后是函数testing的冗余重新定义,它不会产生任何变化。下一条语句调用testing;我们进入例程。

testing(startlocation)
for line in startlocation:

这里的重要部分是 startlocation 是一个 字符串

'[27.994195699999999, -82.569434900000005'

...所以当您执行该循环时,您将遍历字符串,一次一个字符。

更正:

说实话,我不知道测试应该做什么。 看起来你需要做的就是去掉那个前括号:

intlocation = startlocation.split('[')

...或者干脆

intlocation = startlocation[1:]

相反,如果您希望 float 值作为一个二元素列表,(a) 像上面一样敲掉括号,在逗号处拆分元素,然后转换为浮点数:

intlocation = [ float(x) for x in startlocation[1:].split(',') ]

【讨论】:

  • 感谢您的投入和出色的分析。我已经学习 Python 大约两个月了,我不得不说这是我必须做的最复杂的事情。你能进一步解释你的第二点吗?不幸的是,我通过分析有效的方法学得最好,而且我以前从未处理过如此复杂的 txt 输入。
【解决方案2】:

看起来它真正需要的是ast.literal_eval

for line in tinputfile:
    twoparts = line.split("]")
    startlocation = ast.literal_eval(twoparts[0] + ']') # add the ']' back in
    # startlocation is now a list of two coordinates.

但你最好还是使用re

> import re
> example = '[27.994195699999999, -82.569434900000005] 6 2011-08-28 19:02:36 text text text text'
> fmt = re.split(r'\[(-?[0-9.]+),\s?(-?[0-9.]+).\s*\d\s*(\d{4}-\d{1,2}-\d{1,2}\s+\d{2}:\d{2}:\d{2})',example)
> fmt
['', '27.994195699999999', '-82.569434900000005', '2011-08-28 19:02:36', ' text text text text']
> location = (float(fmt[1]), float(fmt[2]))
> time = fmt[3]
> text = fmt[4]

那么,发生了什么事?

正则表达式中的每个(...)re 模块)都告诉re.split“让这件作品成为自己的索引”。

第一个和第二个是-?[0-9.]。这意味着匹配任何可能有减号后跟数字和小数位的内容(我们可以更严格,但您并不真的需要)。

下一组() 匹配任何日期:\d{4} 表示“四位数字”。 \d{1,2} 表示“一位或两位数”。

或者,您可以同时使用两者:

> fmt = re.split(r'\[(-?[0-9.]+,\s?-?[0-9.]+).\s*\d\s*(\d{4}-\d{1,2}-\d{1,2}\s+\d{2}:\d{2}:\d{2})',example)
> fmt # watch what happens when I change the grouping.
['', '27.994195699999999, -82.569434900000005', '2011-08-28 19:02:36', ' text text text text']
> location = literal_eval('(' + fmt[1] + ')')
> time = fmt[2]
> text = fmt[3]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多