Python: получение значений (объектов) из словаря объектов, в котором одно из полей объекта соответствует значению (или условию) - PullRequest
6 голосов
/ 08 марта 2010

У меня есть словарь Python, ключи которого - строки, а значения - объекты.

Например, объект с одной строкой и одним целым

class DictItem:
   def __init__(self, field1, field2):
      self.field1 = str(field1)
      self.field2 = int(field2)

и словарь:

myDict = dict()
myDict["sampleKey1"] = DictItem("test1", 1)
myDict["sampleKey2"] = DictItem("test2", 2)
myDict["sampleKey3"] = DictItem("test3", 3)

Какой самый лучший / самый эффективный способ получить словарные записи, которые имеют поле "field2"> = 2?

Идея заключается в создании «под-словаря» (список тоже подойдет) только с записями, в которых field2> = 2 (в примере будет так):

{
    "sampleKey2": {
        "field1" : "test2",
        "field2": 2 
    },
    "sampleKey3": {
        "field1" : "test3",
        "field2": 3 
    }
}

Есть ли лучший способ, чем пройтись по всем элементам словаря и проверить состояние? Может быть, с помощью itemgetters и лямбда-функций?

Спасибо!

P.S .: Я использую Python2.4, на всякий случай, если это актуально

Ответы [ 5 ]

8 голосов
/ 08 марта 2010

Чтобы сделать dict из вашего dict,

subdict = dict((k, v) for k, v in myDict.iteritems() if v.field2 >= 2)
4 голосов
/ 08 марта 2010
mySubList = [dict((k,v) for k,v in myDict.iteritems() if v.field2 >= 2)]

Документация:

список-понимания , iteritems()

3 голосов
/ 08 марта 2010

Вы должны хранить свои различные записи - то есть экземпляры "DicItem" - внутри списка. Выражение «генератор / список» может легко отфильтровать желаемые результаты.

data = [
   DictItem("test1", 1), 
   DictItem("test2", 2),
   DictItem("test3", 3),
   DictItem("test4", 4),
]

и затем:

results = [item for item in data if item.field2 >= 2]

Это, конечно, создает линейный фильтр. Если вам требуется более линейная скорость для некоторых ваших запросов, контейнерный объект для регистров - в этом случае «список» должен быть специализированным классом, способным создавать индексы данных в нем, так же, как это делает СУБД со своей таблицей. индексов. Это можно легко сделать, извлекая класс из списка и переопределяя методы * append", "insert", "__getitem__", "__delitem__" и "pop".

Если вам нужно это для высокопрофильного приложения, я бы посоветовал вам взглянуть на некоторые системы объектно-ориентированных БД для Python, такие как ZODB и другие.

2 голосов
/ 08 марта 2010

Идея заключается в создании "под-словаря" (список тоже подойдет)

Если вы хотите список, вы можете использовать filter (или itertools.ifilter ):

result_list = filter(lambda x: x.field2 > 2, mydict.values())
0 голосов
/ 08 марта 2010

«Наиболее эффективный» будет зависеть от того, как часто меняется содержимое словаря по сравнению с тем, как часто вы выполняете поиск.

Если словарь часто меняется, и вы выполняете поиск реже, то наиболее эффективный метод будет проходить по элементам iteritems и выбирать объекты, которые соответствуют критериям, используя код, опубликованный Адамом Бернье.

Если словарь мало меняется, и вы выполняете много поисков, то может быть быстрее создать один или несколько обратных словарей, например, один отображает значения «field2» в список объектов, которые имеют это значение.

В качестве альтернативы, если вы собираетесь выполнять сложные запросы, вы можете поместить все данные в базу данных sqllite в памяти и позволить SQL разобраться в них, возможно, с помощью ORM, такого как SqlAlchemy

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...