1

我有一个文本文件,我想将它加载到 Python 中的字典中。

文本看起来像这样,制表符分隔:

表格剂量参考药物药物名称activeingred INJECTABLE; 注射液 20,000 UNITS/ML LIQUAEMIN SODIUM 肝素钠注射液;注射液 40,000 UNITS/ML 肝素钠肝素钠注射液;注射液 5,000 UNITS/ML LIQUAEMIN SODIUM 肝素钠

现在我的代码看起来像这样,但它不起作用(列表索引超出范围,并且没有推送到字典中)。我不知道我哪里错了,不是程序员。谢谢你的帮助。

import sys

def load_medications(filename):
    meds_dict = {}
    f = open(filename)
    l = " "
    # print f.read()
    for line in f:
        fields = l.split("\t")
        ApplNo = fields[0]
        ProductNo = fields[1]
        Form = fields[2]
        Dosage = fields[3]
        ProductMktStatus = fields[4]
        TECode = fields[5]
        ReferenceDrug = fields[6]
            DrugName = fields[7]
        ActiveIngred = fields[8]

        meds = {
                "ApplNo": ApplNo,   
                "ProductNo": ProductNo, 
                "Form": Form,
                "Dosage": Dosage,   
                "ProductMktStatus": ProductMktStatus,
                "TECode": TECode,
                "ReferenceDrug": ReferenceDrug, 
                "DrugName": DrugName,
                "ActiveIngred": ActiveIngred
            }       
        meds_dict[DrugName] = meds
    f.close()
    return meds_dict


def main():
    x = load_medications("druglist.txt")
    print x



if __name__ == "__main__":
    main()
4

7 回答 7

2

尝试line.split而不是l.split

于 2012-08-09T22:50:10.067 回答
2

您可能会更轻松地使用标准库中的 CSV 模块解析这些数据- 如果您使用制表符作为分隔符和;换行符来安装它,那么解析您发布的文件应该没有问题。

使用DictReader还可以更轻松地阅读您的行(您可以将事物称为line['ApplNo']而不是line[0])。

不幸的是,它看起来不像您文件中的标题映射到您想要在代码中调用它们的内容 - 因此您需要根据字典中的内容自己分配字段的名称。

于 2012-08-09T22:55:22.687 回答
1

您应该csv.DictReader对此进行研究,假设您的文件在开头有一个正确的标题行,您应该能够像这样简单地创建字典:

def load_medications(filename):
    reader = csv.DictReader(open(filename), delimiter='\t')
    meds = {}
    for row in reader:
        meds[row['DrugName']] = row
    return meds

如果您的文件没有标题行,您可以将字段名称传递给DictReader初始化程序:

fields = ["ApplNo", "ProductNo", "Form", "Dosage", "ProductMktStatus"
          "TECode", "ReferenceDrug", "DrugName", "ActiveIngred"]
reader = csv.DictReader(open(filename), delimiter='\t', fieldnames=fields)
于 2012-08-09T22:58:24.033 回答
0

我认为您高估了文件的列数。在哪里ApplNoProductNo

于 2012-08-09T22:51:35.767 回答
0

你居然分裂了l,并没有line。你要:

def load_medications(filename):
    meds_dict = {}
    with open(filename) as f: # Ensure that the file gets closed
        for line in f:
            fields = line.split("\t") # line, not l
            keys = ["ApplNo", "ProductNo", "Form", "Dosage", "ProductMktStatus",
                    "TECode", "ReferenceDrug", "DrugName", "ActiveIngred",]

            if len(fields) != len(keys):
                raise ValueError("Malformed input line " + repr(line))

            meds = dict(zip(keys, fields))
            meds_dict[meds["DrugName"]] = meds
    return meds_dict

有关其工作原理的详细信息,请继续阅读zipdict

于 2012-08-09T22:52:03.930 回答
0

看起来您的代码假设特定药物有 9 个属性。您发布的示例文本文件,但是只有 5 个属性。当您调用 时fields = l.split("\t"),将返回一个只有 5 个元素的数组,因为“druglist.txt”中只有 5 个元素。因此,如果您fields使用大于或等于 5 的值进行索引,即fields[8],您将获得“索引超出范围”异常。

于 2012-08-09T23:05:51.517 回答
0

既然您的字段名称都是有效的 Python 标识符,为什么不将您的数据读入 namedtuples 而不是 dicts?

data = """Form Dosage ReferenceDrug drugname activeingred INJECTABLE; INJECTION 20,000 UNITS/ML LIQUAEMIN   SODIUM HEPARIN  SODIUM  INJECTABLE; INJECTION   40,000 UNITS/ML LIQUAEMIN   SODIUM HEPARIN  SODIUM  INJECTABLE; INJECTION   5,000 UNITS/ML  LIQUAEMIN   SODIUM HEPARIN  SODIUM  INJECTABLE""".split('; ')

from collections import namedtuple

# define class DrugData as a namedtuple, using the headers from data[0]
DrugData = namedtuple("DrugData", data[0])

# use a list comprehension to create a DrugData for each data line
druglist = [DrugData(*line.split('\t')) for line in data[1:]]

# access each tuple in druglist, using attribute access to individual fields
for d in druglist:
    print "%s | %s | %s" % (d.ReferenceDrug, d.Form, d.Dosage)

印刷:

LIQUAEMIN | INJECTION | 20,000 UNITS/ML
LIQUAEMIN | INJECTION | 40,000 UNITS/ML
LIQUAEMIN | INJECTION | 5,000 UNITS/ML

编辑:

回顾您最初的问题,您似乎想要创建所有这些条目的单个字典,以drugname. 不幸的是, dict 键必须是唯一的,在您的示例中,所有 3 个条目都具有相同的drugname. 您可能必须组合 2 个或更多字段才能为处理所有这些值的 dict 组成真正唯一的键,例如(drugname, Dosage).

或者,稍微更改您的设计,使每个都drugname指向匹配值列表。最简单的方法是使用 defaultdict 而不是 dict,以便使用空列表自动初始化新条目。在您的代码中,您将添加一个导入语句:

from collections import defaultdict

并将 meds_dict 的声明更改为:

meds_dict = defaultdict(list)

这意味着任何尚未看到的新键都将使用作为 defaultdict 的参数提供的函数/类进行初始化,在这种情况下为list.

然后将新条目添加到 meds_dict,而不是使用“=”进行分配,您将附加到所有匹配药物/剂量的列表中:

meds_dict[DrugName].append(meds)

现在,对于任何 DrugName,您将获得匹配的 Form/Dosage/etc 的列表。记录。

于 2012-08-10T02:06:19.980 回答