2012-05-10 43 views
0

我想将数据保存在文本文件中,并从这些文件创建字典,稍后将传递给函数。Python:需要帮助从文本文件创建字典并拆分列表

这里是我的代码:

def lesson_dictionary(filename): 
    print "Reading file ", filename 
    with open(filename) as f: 
     mylist = f.read().strip().split() 
     dictionary = OrderedDict(zip(mylist[::2], mylist[1::2])) #keep keys/values in same order as declared in mylist 
     print dictionary 
    return dictionary 

随着为sample.txt包含用空格隔开,它工作正常的键/值对的两列的样本文件。例如,

AB

CD

EF

产生像这样的列表:

OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')]) 

,但如果我更改代码和.txt文件的内容,它打破了。例如,如果包括sample2.txt:

A:B

C:d

Ê:F

和我的代码是

def lesson_dictionary(filename): 
    print "Reading file ", filename 
    with open(filename) as f: 
     mylist = f.read().strip().split(':') #CHANGED: split string at colon! 
     dictionary = OrderedDict(zip(mylist[::2], mylist[1::2])) 
     print dictionary 
    return dictionary 

我得到以下输出:

OrderedDict([('a', 'b \nc'), ('d\ne', 'f')]) 

发生了什么?为什么strip()为第一个.txt文件而不是第二个?预先感谢您的帮助。

回答

4

原始split()分裂上的空白,并\n被认为是空白。通过更改为split(':'),您已删除行尾的分隔符,因此一行的结尾与下一行的开头合并,并在中间带有一个额外的换行符。我不认为有一个简单的方法来修复它,除了一次读取一行文件。

编辑:一些代码来演示。

dictionary = OrderedDict() 
with open(filename) as f: 
    for line in f: 
     key, value = line.split(':') 
     dictionary[key.strip()] = value.strip() 

以上原件的精神:

with open(filename) as f: 
    mylist = [line.strip().split(':') for line in f] 
    dictionary = OrderedDict(mylist) 

第二种形式具有不自动从周围的话剥离空白的缺点。根据你的例子,你可能需要这个。

+0

我真的建议的替代标记表明“......除了一次读取文件的一行。”让文件对象分割线,例如f'中的行将更具可读性。 – Leovt

+0

感谢您的意见,@Leovt。 – user1186742

+0

这工作完美!非常感谢你的解释和示例代码,马克。 – user1186742

0

如果你自己创建输入文件,我相信json会更适合这个问题。

您可以使用它像这样:

import json 

#write the dictionary to a file 
outfile = open(filename, 'w') 
json.dump(someDictionary, outfile) 

#read the data back in 
with open(filename) as infile: 
    newDictionary = json.load(infile) 
0

你试过打印出的myList内容?

myList = ["a", "b c", "d e", "f"] 

,如果你想让他们的行为方式相同第一空格替换冒号:

myList = f.read().replace(":", "").split() 

或者,如果你希望他们分割成键值对,只是使用字符串的切片,甚至拉链和奇数元素一起:

s = f.read().split() 
myDict = dict(zip(s[::2], s[1::2])) 
2

split()没有分隔符在空格上分裂,这是空行和换行符/空格。如果冒号为split,则该算法不再适用,所以换行符会显示在输出中。尝试:

dictionary = Ordereddict(l.strip().split(':') for l in f) 
+0

非常感谢@spinlok的解释。您的示例代码起作用并且非常有用。这也很简单直接。与Mark的方式相反,在一条线上进行拍摄是否有优势? – user1186742

+0

@ user1186742,这样做使用一半的内存,因为你不一次创建一个列表,你会得到一个发生器,一次为OrderedDict提供一个项目。 –

0

如果你想你的代码分隔中立,即a:ba-ba#b和这样的。而不是常规split()使用re.split()

import re 
pattern = re.compile(r"[^\w]")  # non-w char 
with open(filename, "rt") as fr: 
    return OrderedDict(pattern.split(l.strip()) for l in fr)