在迭代

时间:2017-05-19 16:01:43

标签: python dictionary

为了从空值中过滤字典列表,我需要从字典中删除约30%的数据。

所以我最终得到了这段代码:

   qr = query_result
   for row in qr:
        for key, value in row.items():
            if value ==' ' or value == None, value == '':
                del row[key]

但是,在第一次删除尝试时执行时出错:

RuntimeError: dictionary changed size during iteration

在stackoverflow上进行了一些搜索之后,我发现solution,这涉及将所有已删除的值复制到单独的列表中以便后续删除。

delete = []
for k,v in dict.items():
    if v%2 == 1:
        delete.append(k)
for i in delete:
    del dict[i]

这种方法,转换成我的案例的代码:

qr = query_result
for row in qr:
    delete = []
    for key, value in row.items():
        if value == ' ' or value == '' or value == None:
            delete.append(key)
    for i in delete:
        del row[i]

也会遇到某些RuntimeError

因此,删除循环应该在dict foreach循环之外:

qr = query_result
for row in qr:
    delete = []
    for key, value in row.items():
        if value == ' ' or value == '' or value == None:
            delete.append(key)
for i in delete:
    del row[i]

但遗憾的是,给定代码只能在最后一行正确修改。

如何处理所有行然后删除垃圾数据?

以下是一些测试数据:

c = [{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''},
    {'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}]

我的输出:

{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}
{'A': 'B', 'C': '3', 'P': '343'}

期望的输出:

{'A': 'B', 'C': '3', 'P': '343'}
{'A': 'B', 'C': '3', 'P': '343'}

3 个答案:

答案 0 :(得分:2)

以下是修改第一个示例的版本,您需要“复制”您的列表以与其进行迭代并同时删除。在使用复制的列表进行迭代后,您可以根据需要从原始列表中删除。

import copy

qr = [{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''},
    {'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}]

for i, row in enumerate(copy.deepcopy(qr)):
     for key, value in row.items():
         if value in {' ', None, ''}:
             del qr[i][key]

print(qr)

除此之外,通常您要创建一个新列表,而不是从原始列表中删除。一个简单的列表理解就可以解决这个问题:

qr = [{k:v for k, v in row.items() if v not in {' ', None, ''}} for row in qr]

print(qr) # same result

两者的输出:

[{'A': 'B', 'C': '3', 'P': '343'},
 {'A': 'B', 'C': '3', 'P': '343'}]

答案 1 :(得分:1)

您的方法(在迭代时收集密钥,之后删除)是正确的。

这是你的问题:

qr = query_result
for row in qr:
    delete = []  # <--- here

每次触摸新行时,都会创建一个新的delete列表。如果从前一行留下任何数据,则会丢失。

相反,您应该在随后使用它的同一级别(缩进)上创建它:

delete = []  # Only once for all rows.
qr = query_result
for row in qr:
   # ...

for k in delete:
  del data[k]

答案 2 :(得分:0)

单行:

c = [{k: v for k, v in d.items() if v not in [' ', '', None]} for d in c]

循环遍历c的元素,然后对每个元素仅返回匹配的键值对。这将返回:

[{'A': 'B', 'P': '343', 'C': '3'}, {'A': 'B', 'P': '343', 'C': '3'}]