Как найти значение ключа из совпадения значения ключа? - PullRequest
1 голос
/ 24 марта 2020

У меня действительно очень длинный упорядоченный dict, который выглядит примерно так:

OrderedDict([('JIRAUSER16100', {'name': 'john.smith', 'fullname': 'John Smith', 'email': 'John.Smith@domain.test', 'active': True}), ('JIRAUSER16300', {'name': 'susan.jones', 'fullname': 'Susan Jones', 'email': 'Susan.Jones@domain.test', 'active': True})])

Как я могу искать в этом списке, чтобы найти значение ключа, основанное на совпадении значения ключа? Например, для Сьюзен Джонс я хотел бы найти ее электронную почту, основываясь на значении имени? Есть ли способ pythoni c, чтобы найти это, не просто просматривая весь словарь?

В настоящее время я просто делаю это ниже, но это кажется неэффективным, когда мне приходится go просматривать список тысяч раз. Мне интересно, есть ли какой-нибудь метод "поиска"?

searchname = "susan.jones"
for user in my_ordered_dict.items():
   if user[1]["name"] == searchname:
      print(user[1]["email"])

Ответы [ 2 ]

1 голос
/ 24 марта 2020

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

1) используйте Pandas:

In [1]: from collections import OrderedDict

In [2]: import pandas as pd

In [3]: d = OrderedDict([
   ...:     ('JIRAUSER16100', {'name': 'john.smith',
   ...:                        'fullname': 'John Smith',
   ...:                        'email': 'John.Smith@domain.test',
   ...:                        'active': True}),
   ...:     ('JIRAUSER16300', {'name': 'susan.jones',
   ...:                        'fullname': 'Susan Jones',
   ...:                        'email': 'Susan.Jones@domain.test',
   ...:                        'active': True})
   ...: ])
In [4]: df = pd.DataFrame(d).T

In [5]: df
Out[5]:
                      name     fullname                    email active
JIRAUSER16100   john.smith   John Smith   John.Smith@domain.test   True
JIRAUSER16300  susan.jones  Susan Jones  Susan.Jones@domain.test   True

In [6]: df.loc[df['name'] == 'susan.jones', 'email'][0]
Out[6]: 'Susan.Jones@domain.test'

По шкале от простого к изучению, но слабого до трудного для изучения, но мощного, pandas довольно далеко от последняя крайность Здесь можно распаковать приличную сумму, если вы не знакомы с pandas, поэтому для краткости я не буду в нее go. Но не стесняйтесь комментировать любые вопросы, если вам помогут дополнительные объяснения.

2) Используйте встроенную next функцию

Это позволит вам избежать зацикливания через полный словарь. Чтобы сделать длинную историю действительно короткой, вы можете передать next генератор с троичным выражением, и он будет по существу проходить через итерацию, пока не найдет первый элемент, который удовлетворяет данному условию. Так что в вашем случае

In [7]: next(entry['email'] for entry in d.values() if entry['name'] == 'susan.jones')
Out[7]: 'Susan.Jones@domain.test'

будет работать. Это сэкономит вам время стихов, повторяющих весь диктовку, но в отличие от варианта 1, его скорость будет зависеть от того, где в вашей OrderedDict находится запись, которую вы пытаетесь найти. Если по какой-то причине вам не нужно придерживаться исключительно стандартной библиотеки, Pandas будет намного быстрее для любого набора данных разумного размера.

Надеюсь, это поможет!

0 голосов
/ 24 марта 2020

Если вы ищете конкретное совпадение c, вам придется перебирать свою структуру, пока не найдете ее, поэтому вам не нужно go просматривать весь словарь.

Что-то вроде:

In [19]: d = OrderedDict([('JIRAUSER16100', {'name': 'john.smith', 'fullname': 'John Smith', 'email': 'John.Smith@domain.test', 
    ...: 'active': True}), ('JIRAUSER16300', {'name': 'susan.jones', 'fullname': 'Susan Jones', 'email': 'Susan.Jones@domain.tes
    ...: t', 'active': True})]) 
    ...:                                                                                                                        

In [20]: def find_entry_by_subkey(sub_key, sub_key_value, data): 
    ...:     for entry in data.values(): 
    ...:         if entry[sub_key] == sub_key_value: 
    ...:             return entry 
    ...:                                                                                                                        

In [21]: find_entry_by_subkey('email', 'Susan.Jones@domain.test', d)                                                            
Out[21]: 
{'name': 'susan.jones',
 'fullname': 'Susan Jones',
 'email': 'Susan.Jones@domain.test',
 'active': True
...