有条件地用理解来替换python字典值

时间:2015-07-08 14:05:19

标签: python csv dictionary list-comprehension nonetype

我正在通过csv.DictReader在csv中阅读,并尝试将所有空值替换为None值。 DictReader似乎将文件作为字典的实例,其中CSV的每一行都是字典(我很好)。但是当我尝试按行/词典遍历行/词典并用""替换任何空值(None)时,我似乎无法解开。我以前写过这个像这样的列表理解:

    for row in data:
        row = [None if not x else x for x in row]

但我需要切换到使用字典而不是列表。我之前没有任何字典理解经验,但是当我尝试将其扩展到字典时,我无法让它工作。我正在思考以下几点:

    for row in data:
        row.values() = [None if not x else x for x in row.values()}

但我得到SyntaxError: invalid syntax.。我已经尝试了很多其他的东西(这里列出的太多了),比如:

    for row in data:
        row = {k:None for k,v in row if v not v else v}

但这似乎也有同样的问题。

作为参考,我的数据如下:

    {'colour': 'ab6612', 'line': '1', 'name': 'Baker', 'stripe': ''}
    {'colour': 'f7dc00', 'line': '3', 'name': '', 'stripe': 'FFFFFF'}

理想情况下最终会成为:

    {'colour': 'ab6612', 'line': '1', 'name': 'Baker', 'stripe': None}
    {'colour': 'f7dc00', 'line': '3', 'name': None, 'stripe': 'FFFFFF'}

3 个答案:

答案 0 :(得分:3)

您的问题是您正在更改名称row以引用for循环中的新字典,这不会更改原始列表/ DictReader对象中的任何内容 - data

如果数据是列表,则应枚举data并更改数据中的字典(或使该引用成为新字典)

示例 -

for i,row in enumerate(data):
     data[i] = {k:(v if v else None) for k,v in row.items()}

示例测试 -

>>> data = [{1:2 , 3:''},{4:'',5:6}]
>>> for i,row in enumerate(data):
...     data[i] = {k:(v if v else None) for k,v in row.items()}
...
>>> data
[{1: 2, 3: None}, {4: None, 5: 6}]

由于您使用的是DictReader类,因此无法直接更改DictReader对象,因此您应该创建一个新列表,并在新列表中添加更改的行(或者DictWriter对象,更喜欢DictWriter对象) -

示例 -

>>> newdata = []
>>> for row in data:
...     newdata.append({k:(v if v else None) for k,v in row.items()})

答案 1 :(得分:0)

您的主要错误是您尝试在字典上迭代两次,而您只需要执行一次。

尝试:

data = {k:(v if v else None) for k,v in data.items()}

没有for-loop。

答案 2 :(得分:0)

如果您使用的是CSV并且数据太大,请使用iteritems()

  

这将节省防止由items()引起的大型列表生成   尝试:

new_data=[]    
for row in data:
    new_data.append({k:(v if v else None) for k,v in row.iteritems()})
  

如果你不理解理解,请遵循这个简单的for循环:

for row in data:
    for k,v in row.iteritems():
        if not v:
            row[k]=None
  

第二种方法很容易理解,也没有创建额外的列表,这对于更高的性能更好