如果字典键的值在其他列表中,则从列表中的字典中删除元素

时间:2019-04-05 10:18:38

标签: python python-3.x

我有如下代码:

dicts = [
        {'one': 'hello',
         'two': 'world',
         'three': ['a', 'b', 'c', 'd'],
         'four': 'foo'
        },
        {'one': 'pizza',
         'two': 'cake',
         'three': ['f', 'g', 'h', 'e'],
         'four': 'bar'
        }
       ]

letters = ['q', 'w', 'e', 'r','t','y']

dedup_rows = [row for row in dicts if row['three'][3] not in letters]

目标是dedup_rows应该包含dicts中的元素,其中three中存储的列表的第四个元素不包含在列表letters中。本质上是delete row from dicts if row['three'][3] in letters。上面代码的输出将是:

dedup_rows: [
             {'one': 'hello',
              'two': 'world',
              'three': ['a', 'b', 'c', 'd'],
              'four': 'foo'
             }
            ]

我正在使用的代码正在运行,但实际上dictsletters都包含成千上万个元素,因此执行速度很慢,因为dicts上的每次迭代都需要完整的迭代超过letters

在Python中是否有更优化的方法?

2 个答案:

答案 0 :(得分:4)

您的代码dedup_rows = [row for row in dicts if row['three'][3] not in letters]具有平方复杂度。因为它在dicts的每个元素上遍历lettersdicts
如果两个列表都包含大量元素。您应该考虑查找时间复杂度约为1的数据结构。对于您的情况,Python Sets很完美。您可以阅读更多有关它的信息。
您需要做的就是将letters = ['q', 'w', 'e', 'r','t','y']转换为语法为set(letters)的集合,并以语法x in letters_set查找。

dicts = [
    {'one': 'hello',
     'two': 'world',
     'three': ['a', 'b', 'c', 'd'],
     'four': 'foo'
    },
    {'one': 'pizza',
     'two': 'cake',
     'three': ['f', 'g', 'h', 'e'],
     'four': 'bar'
    }
   ]

letters = ['q', 'w', 'e', 'r','t','y']
letters_set = set(letters)

dedup_rows = [row for row in dicts if row['three'][3] not in letters_set]
  

像这样,您可以将算法从n平方的顺序更改为n的顺序。

答案 1 :(得分:1)

如果您实际上要处理成千上万的记录,每个记录中的行各具有成千上万的值,那么也许纯粹的内存python方法并不是最好的方法。

您可以采取一些措施来提高性能:

  • 从源(文件?数据库?)中流式传输记录,而不是一次加载
  • 使用一种生成器,该生成器一次读取一个记录,然后在它们不匹配时产生它们(永远不要将它们放在列表中)
  • 将集合用于集合比较,这对于许多值而言将更快

不过,总的来说,这引出了您从何处获取这些记录的问题?

如果它们存储在任何类型的数据库中,则在源代码处执行查询,以排除不需要的行,并提供一个游标以内存高效的方式遍历您想要的行,听起来像是更好的方法。