代码之家  ›  专栏  ›  技术社区  ›  madik_atma

从csv只转换列到dict

  •  1
  • madik_atma  · 技术社区  · 6 年前

    在这个方向上已经有问题,但在我的情况下,我有以下问题:

    列别名包含字典。如果我使用csv阅读器,我会得到字符串。

    我已经用ast eval解决了这个问题,但是它非常慢并且消耗了很多资源。

    由于编码的原因,替代json.loads不起作用。

    有什么解决办法吗?

    CSV文件:

    id;name;partei;term;wikidata;alias
    2a24b32c-8f68-4a5c-bfb4-392262e15a78;Adolf Freiherr Spies von Büllesheim;CDU;10;Q361600;{}
    9aaa1167-a566-4911-ac60-ab987b6dbd6a;Adolf Herkenrath;CDU;10;Q362100;{}
    c371060d-ced3-4dc6-bf0e-48acd83f8d1d;Adolf Müller;CDU;10;Q363453;{'nl': ['Adolf Muller']}
    41cf84b8-a02e-42f1-a70a-c0a613e6c8ad;Adolf Müller-Emmert;SPD;10;Q363451;{'de': ['Müller-Emmert'], 'nl': ['Adolf Muller-Emmert']}
    15a7fe06-8007-4ff0-9250-dc7917711b54;Adolf Roth;CDU;10;Q363697;{}
    

    代码:

    with open(PATH_CSV+'mdb_file_2123.csv', "r", encoding="utf8") as csv8:
        csv_reader = csv.DictReader(csv8, delimiter=';')
        for row in csv_reader:
    
            if not (ast.literal_eval(row['alias'])):
                pass
    
            elif (ast.literal_eval(row['alias'])):
                known_as_list = list()
    
                for values in ast.literal_eval(row['alias']).values():
                    for aliases in values:
                        known_as_list.append(aliases)
    

    它工作得很好,但速度很慢。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Swadhikar    6 年前

    ast 库消耗大量内存(请参阅 this link )我建议在将一个简单的字典格式字符串转换为python字典时避免使用它。相反,我们可以尝试python的内置 eval 函数来克服由于导入模块而导致的延迟。一些讨论表明 评估 在处理敏感的字符串时非常危险。例子: eval('os.system("rm -rf /")') . 但是,如果我们非常确定csv内容不会携带如此敏感的命令,我们可以使用 评估 不用担心。

    with open('input.csv', encoding='utf-8') as fd:
        csv_reader = csv.DictReader(fd, delimiter=';')
    
        for row in csv_reader:
            # Convert dictionary in string format to python format
            row['alias'] = eval(row['alias'])
    
            # Filter empty dictionaries
            if not bool(row['alias']):
                continue
    
            known_as_list = [aliases for values in row['alias'].values() for aliases in values]
    
            print(known_as_list)
    

    输出

    C:\Python34\python.exe c:\so\51712444\eval_demo.py
    ['Adolf Muller']
    ['Müller-Emmert', 'Adolf Muller-Emmert']
    
        2
  •  0
  •   gboffi    6 年前

    你可以避免打电话 literal_eval 三次(一次足够) 当我在这里的时候,我已经清理了,或者我认为,你的代码使用了 经典(3013张赞成票!)贡献

    from ast import literal_eval
    
    # https://stackoverflow.com/a/952952/2749397 by Alex Martelli
    flatten = lambda l: [item for sublist in l for item in sublist]
    ...
    
    for row in csv_reader:
        known_as_list = flatten(literal_eval(row['alias']).values())
    

    从OP显示的数据摘录来看,似乎有可能 避免打电话 字面评价 在行的重要部分

    ...
    for row in csv_reader:
        if row['alias'] != '{}':
            known_as_list = flatten(literal_eval(row['alias']).values())