Python - 将文件导入NamedTuple
最近我有个关于数据类型的问题。
从那以后,我一直在尝试使用命名元组(效果好坏不一)。
我现在遇到的问题是:
- 如何从文件中导入行到新的元组中,
- 如何将用空格、制表符(或者其他分隔符)分开的值导入到元组的指定部分?
比如:
Monday 8:00 10:00 ETR_28135 lh1n1522 Computer science 1
Tuesday 12:00 14:00 ETR_28134 lh1n1544 Geography EA 1
第一行应该放到元组的第一个位置,也就是元组[0]。第一个数据:元组[0].day;第二个:元组[0].start;依此类推。
当新的一行开始时(也就是两个制表符\t),就开始一个新的元组,比如元组[1]。
我用这个来分隔数据:
with open(Filename) as f: for line in f: rawData = line.strip().split('\t')
而其余的逻辑还没有完成(填充元组的部分)。
(我知道,这个问题和之前的问题都很基础。不过,希望这些能帮助到其他人。如果你觉得这不是一个真正的问题,或者太简单了,可以投票关闭。谢谢你的理解。)
3 个回答
3
这里有一个简单的方法来处理这些事情。首先,声明一个行项目的类:
fields = "dow", "open_time", "close _time", "code", "foo", "subject", "bar"
Item = namedtuple('Item', " ".join(fields))
接下来的部分是在你的循环里面。
# this is what your raw data looks like after the split:
#raw_data = ['Monday', '8:00', '10:00', 'ETR_28135', 'lh1n1522', 'Computer science', '1']
data_tuple = Item(**dict(zip(fields, raw_data)))
现在慢慢来解释:
zip(fields, raw_data)
会创建一个成对的列表,比如[("dow", "Monday"), ("open_time", "8:00"),..]
,就是把字段和原始数据配对在一起。- 然后
dict()
会把这个成对的列表变成一个字典,像这样{"dow": "Monday", "open_time": "8:00", ..}
。 - 接着
**
会把这个字典当作一堆关键字参数传给Item
的构造函数,相当于Item(dow="Monday", open_time="8:00",..)
。
所以你的项目就是命名元组,所有的值都是字符串。
补充:
如果字段的顺序不会改变,你可以更简单地做到这一点:
data_tuple = Item(*raw_data)
这利用了文件中字段的顺序和 Item
定义中参数的顺序是匹配的这个事实。
3
如果你想使用命名元组(NamedTuple),可以参考一下Python文档中稍微修改过的例子:
MyRecord = namedtuple('MyRecord', 'Weekday, start, end, code1, code2, title, whatever')
import csv
for rec in map(MyRecord._make, csv.reader(open("mycsv.csv", "rb"), delimiter='\t')):
print rec.weekday
print rec.title
# etc...
12
这种数据库文件被称为“逗号分隔值”,虽然实际上它们并不是用逗号分开的。Python有一个很方便的库叫做csv
,可以让你轻松读取这样的文件。
下面是一个稍微修改过的文档中的例子。
csv.register_dialect('mycsv', delimiter='\t', quoting=csv.QUOTE_NONE)
with open(filename, 'rb') as f:
reader = csv.reader(f, 'mycsv')
通常你一次处理一行数据。如果你需要把整个文件放在一个元组中,可以这样做:
t = tuple(reader)
编辑
如果你想通过字段名来访问数据,可以使用csv.DictReader,不过我不太清楚具体怎么用,也没法在这里测试。
编辑 2
关于命名元组的内容,我有点跟不上了。这里有一个很好的例子,展示了命名元组如何与csv模块一起使用:
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for line in csv.reader(open("employees.csv", "rb")):
emp = EmployeeRecord._make(line)
print emp.name, emp.title