Pythonic способ разобрать список словарей для определенного атрибута? - PullRequest
2 голосов
/ 11 апреля 2011

Я хочу сделать перекрестную ссылку на словарь и набор запросов django, чтобы определить, какие элементы имеют уникальные значения dictionary['name'] и djangoModel.name соответственно.Теперь я делаю это следующим образом:

  • Создайте список значений словаря ['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 выше), просто чтобы иметь возможность проверить включение сразу после.Я что-то пропустил?Я полагаю, я мог бы поместить два списка в одну строку, например, так:

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 ]

4 голосов
/ 11 апреля 2011
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())]
2 голосов
/ 11 апреля 2011

Операции intersection - и difference наборов должны помочь вам более элегантно решить вашу проблему.

Но поскольку вы изначально имеете дело с диктовками, эти примеры и обсуждениеможет дать некоторые вдохновения: http://code.activestate.com/recipes/59875-finding-the-intersection-of-two-dicts

2 голосов
/ 11 апреля 2011

Вы работаете с основными операциями над множествами здесь. Вы можете преобразовать ваши объекты в наборы и просто найти пересечение (подумайте, диаграммы Венна):

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

Наборы действительно полезны при сравнении двух списков объектов (псевдоним):

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...