Как извлечь из Python dict, где ключ известен только частично? - PullRequest
12 голосов
/ 13 августа 2011

У меня есть dict, у которого есть ключи строкового типа, точные значения которых я не могу знать (потому что они генерируются динамически в другом месте).Тем не менее, я знаю, что этот ключ, который я хочу, содержит определенную подстроку, и что единственный ключ с этой подстрокой определенно находится в требовании.

Какой самый лучший или «самый питонический» способ получить значение дляэтот ключ?

Я подумал о двух стратегиях, но оба меня раздражают:

for k,v in some_dict.items():
    if 'substring' in k:
        value = v
        break

- ИЛИ -

value = [v for (k,v) in some_dict.items() if 'substring' in k][0]

Первый метод громоздкий и нескольконекрасиво, хотя второе чище, но дополнительный шаг индексации в понимании списка ([0]) раздражает меня.Есть ли лучший способ выразить вторую версию или более краткий способ написать первую?

Ответы [ 5 ]

10 голосов
/ 13 августа 2011

Существует возможность написать вторую версию с атрибутами производительности первого.

Использовать выражение генератора вместо понимания списка:

value = next(v for (k,v) in some_dict.iteritems() if 'substring' in k)

Выражение в скобках вернет итератор, который вы затем попросите предоставить следующий, то есть первый элемент.Дальнейшие элементы не обрабатываются.

1 голос
/ 13 августа 2011

Если ключей много, но строку легко восстановить из подстроки, ее можно будет быстрее восстановить.например, часто вы знаете начало ключа, но не дату, к которой добавлена ​​метка.(таким образом, вам, возможно, придется только попробовать 365 дат, а не перебирать миллионы ключей, например).Это вряд ли так, но я подумал, что в любом случае предложу это.например,

>>> names={'bob_k':32,'james_r':443,'sarah_p':12}
>>> firstname='james' #you know the substring james because you have a list of firstnames
>>> for c in "abcdefghijklmnopqrstuvwxyz":
...     name="%s_%s"%(firstname,c)
...     if name in names:
...             print name
... 
james_r
1 голос
/ 13 августа 2011
class MyDict(dict):
    def __init__(self, *kwargs):
        dict.__init__(self, *kwargs)

    def __getitem__(self,x):
        return next(v for (k,v) in self.iteritems() if x in k)



# Defining several dicos ----------------------------------------------------    
some_dict = {'abc4589':4578,'abc7812':798,'kjuy45763':1002}

another_dict = {'boumboum14':'WSZE x478',
                'tagada4783':'ocean11',
                'maracuna102455':None}

still_another = {12:'jfg',45:'klsjgf'}



# Selecting the dicos whose __getitem__ method will be changed -------------       
name,obj = None,None
selected_dicos = [ (name,obj) for (name,obj) in globals().iteritems()
                   if type(obj)==dict
                   and all(type(x)==str for x in obj.iterkeys())]

print 'names of selected_dicos ==',[ name for (name,obj) in selected_dicos] 



# Transforming the selected dicos in instances of class MyDict -----------
for k,v in selected_dicos:
    globals()[k] = MyDict(v)



# Exemple of getting a value ---------------------------------------------      
print "some_dict['7812'] ==",some_dict['7812']

результат

names of selected_dicos == ['another_dict', 'some_dict']
some_dict['7812'] == 798
1 голос
/ 13 августа 2011

Как насчет этого:

value = (v for (k,v) in some_dict.iteritems() if 'substring' in k).next()

Он немедленно остановится, когда найдет первое совпадение.

Но он все еще имеет сложность O (n), где n - количество пар ключ-значение. Вам нужно что-то вроде списка суффиксов или дерева суффиксов, чтобы ускорить поиск.

0 голосов
/ 13 августа 2011

Я предпочитаю первую версию, хотя я бы использовал some_dict.iteritems() (если вы на Python 2), потому что тогда вам не нужно заранее составлять полный список всех элементов. Вместо этого вы перебираете диктовку и ломаетесь, как только закончите.

В Python 3 some_dict.items(2) уже приводит к представлению в словаре, так что это уже подходящий итератор.

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