以Pythonic方式解析字典列表中特定属性?

2 投票
3 回答
2706 浏览
提问于 2025-04-16 15:30

我想要对比一个字典和Django的查询集,看看哪些元素在各自的dictionary['name']djangoModel.name中是独一无二的。现在我做法是:

  • 先创建一个包含字典中所有dictionary['name']值的列表
  • 再创建一个包含djangoModel.name值的列表
  • 通过检查这些列表来生成唯一值的列表

这个过程看起来是这样的:

alldbTests = dbp.test_set.exclude(end_date__isnull=False)   #django queryset

vctestNames = [vctest['name'] for vctest in vcdict['tests']]   #from dictionary
dbtestNames = [dbtest.name for dbtest in alldbTests]    #from django model

# Compare tests in protocol in fortytwo's db with protocol from vc

obsoleteTests = [dbtest for dbtest in alldbTests if dbtest.name not in vctestNames]
newTests = [vctest for vctest in vcdict if vctest['name'] not in dbtestNames]

我觉得这样生成中间的名字列表(上面第2和第3行)有点不太符合Python的风格,因为我只是为了能马上检查包含关系。难道我漏掉了什么吗?我想我可以把两个列表推导放在一行里,像这样:

obsoleteTests = [dbtest for dbtest in alldbTests if dbtest.name not in [vctest['name'] for vctest in vcdict['tests']]]

但这样似乎更难理解。

编辑:想象一下最初的状态是这样的:

# vcdict is a list of django models where the following are all true
alldBTests[0].name == 'test1'
alldBTests[1].name == 'test2'
alldBTests[2].name == 'test4'

dict1 = {'name':'test1', 'status':'pass'}
dict2 = {'name':'test2', 'status':'pass'}
dict3 = {'name':'test5', 'status':'fail'}

vcdict = [dict1, dict2, dict3]

我不能直接转换成集合并取差集,除非我只保留名字字符串,但那样我就无法访问模型或字典的其他部分,对吧?只有在两者都是同类型对象的情况下,集合才适用。

3 个回答

2

集合的 intersection(交集)和 difference(差集)操作可以帮助你更优雅地解决问题。

不过因为你最开始是在处理字典,这些例子和讨论可能会给你一些启发:http://code.activestate.com/recipes/59875-finding-the-intersection-of-two-dicts

2

你在这里处理的是基本的集合操作。你可以把你的对象转换成集合,然后找到它们的交集(可以想象成维恩图):

obsoleteTests = list(set([a.name for a in alldbTests]) - set(vctestNames))

集合在比较两个对象列表时非常有用(伪Python代码):

set(a) - set(b)             = [c for c in a and not in b]
set(a) + set(b)             = [c for c in a or in b]
set(a).intersection(set(b)) = [c for c in a and in b]
4

在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后把它放到另一个地方。这就像是把书从一个书架搬到另一个书架一样。

有些时候,我们会遇到一些问题,比如数据格式不对,或者数据丢失了。这就像是你搬书的时候,发现有些书掉了,或者书的封面被撕坏了。

为了避免这些问题,我们可以使用一些工具或者方法来帮助我们。比如,我们可以检查数据的完整性,确保所有的数据都在,而且格式是正确的。这样就能减少出错的机会。

总之,处理数据就像搬家一样,需要小心翼翼,确保每一件东西都能安全到达目的地。

vctestNames = dict((vctest['name'], vctest) for vctest in vcdict['tests'])
dbtestNames = dict((dbtest.name, dbtest) for dbtest in alldbTests)

obsoleteTests = [vctestNames[key]
                 for key in set(vctestNames.keys()) - set(dbtestNames.keys())]

newTests = [dbtestNames[key]
            for key in set(dbtestNames.keys()) - set(vctestNames.keys())]

撰写回答