Наличие некоторых ошибок с Loops словарей в Python - PullRequest
0 голосов
/ 30 июня 2018

Я хочу составить программу винного меню с указанием 1) названия и 2) цены на вино, если клиенты ставят название вина с Python 3. Для этого я составил винную карту, состоящую из словарей, как показано ниже.

wine = [
{'Origin': 'A', 'Name': 'w1', 'price': 10000},
{'Origin': 'B', 'Name': 'w2', 'price': 2000},
{'Origin': 'C', 'Name': 'w3', 'price': 4000},
{'Origin': 'D', 'Name': 'w3', 'price': 55000},
{'Origin': 'E', 'Name': 'w2', 'price': 63000},
{'Origin': 'F', 'Name': 'w6', 'price': 80000}
]

wish_wine = input('Insert the wine what you want to have : ')

Алгоритм, который я пытаюсь реализовать, следующий:

1) Попробуйте найти все элементы в списке, есть ли вино, которое хочет клиент:

2) Если есть в списке, вернуть все результаты с указанием их имени и цены.

3) Если в списке нет вина, выведите сообщение «Извините, вина нет ...»

for i in range(len(wine)):
    if wish_wine in wine[i]['Name']:
        print('wine', wine[i]['Name'], 'is', wine[i]['price'], '$'.)
else:
    print('Sorry, there is no wine what you want.')

Вот коды, которые я сделал на данный момент, это хорошо работает в случае 3), но также показывает сообщение «Извините, вина нет ...» даже в случае 2).

Спасибо!

Ответы [ 3 ]

0 голосов
/ 30 июня 2018

Возможно, вы специально намеревались использовать эту JSON-подобную структуру данных, но рассматривали ли вы схему поиска в хеш-таблице?

>>> wine = [
...     {'Origin': 'A', 'Name': 'w1', 'price': 10000},
...     {'Origin': 'B', 'Name': 'w2', 'price': 2000},
...     {'Origin': 'C', 'Name': 'w3', 'price': 4000},
...     {'Origin': 'D', 'Name': 'w3', 'price': 55000},
...     {'Origin': 'E', 'Name': 'w2', 'price': 63000},
...     {'Origin': 'F', 'Name': 'w6', 'price': 80000}
... ]
>>> 
>>> wine_dict_lookup = {row['Name']: {'Origin': row['Origin'], 'price': row['price']} for row in wine}
>>> wine_dict_lookup
{'w1': {'Origin': 'A', 'price': 10000}, 'w2': {'Origin': 'E', 'price': 63000}, 'w3': {'Origin': 'D', 'price': 55000}, 'w6': {'Origin': 'F', 'price': 80000}}
>>> wish_wine = input('Insert the wine what you want to have : ')
>>> try:
...     print('wine', wish_wine, 'is', wine_dict_lookup[wish_wine]['price'], '$')
... except KeyError:
...     print('Sorry, there is no wine what you want.')
... 
wine w1 is 10000 $

Эта проблема очень хорошо подходит для хеш-таблицы, такой как словарь. Хотя, если вы хотите, чтобы строка if wish_wine in wine[i]['Name']: служила своего рода инструментом нечеткого поиска (т. Е. Чтобы можно было сопоставить строку типа «Я хочу w1 »), то разница в производительности между этими двумя подходы незначительны.

Настоящим преимуществом использования словаря является то, что поиск составляет O(1), что означает постоянное время относительно количества различных вин, которые у вас есть. Ваш поиск по списку O(n), где n - это количество элементов в вашей винной карте, потому что вы перебираете потенциально все вина, чтобы найти то, что кто-то искал.

0 голосов
/ 30 июня 2018

Вы можете использовать collections.defaultdict, чтобы реструктурировать свой словарь, чтобы упорядочить по названию вина. Это работает, только если вы ищете точное совпадение имени.

from collections import defaultdict

wine_d = defaultdict(list)

for item in wine:
    wine_d[item['Name']].append(item)

Тогда доступ к информации для входного имени вина тривиален:

wish_wine = input('Insert the wine what you want to have : ')

print(wine_d.get(wish_wine, 'No wine found'))
0 голосов
/ 30 июня 2018

Вам не хватает оператора break или флага, указывающего, что вы нашли результаты.

Кроме того, вместо итерации по range(len(wine)) вы можете выполнять итерацию прямо по списку вин, который возвращает одно вино для каждой итерации. Это сделает ваш код более читабельным, понятным и эффективным:

wines_found = False
for w in wine:
    if wish_wine in w['Name']:
        print('wine', wine['Name'], 'is', wine['price'], '$'.)
        wines_found = True

if not wines_found:
    print('Sorry, there is no wine what you want.')

Имейте в виду, что если ваше вино называется "Мерло" и вы проверите M in "Merlot", вы обнаружите, что оно прошло. Это станет проблемой, если у вас есть несколько вин, начиная с M.

Если вы хотите избежать этого, измените if wish_wine in w['Name'] на if wish_wine == w['Name'] и добавьте break.

...