2013-04-16 3 views
0

Я работаю со словарями в первый раз. Я хотел бы знать, как я могу подсчитать, сколько ключевых пар значений есть в каждом словаре, где значение «доступно». Я знаю, что я, вероятно, использую len().подсчет количества пар значений ключа в словаре

seats = { 
    'A': {'A1':'available', 'A2':'unavailable', 'A3':'available'}, 
    'B': {'B1':'unavailable', 'B2':'available', 'B3':'available'}, 
    'C': {'C1':'available', 'C2':'available', 'C3':'unavailable'}, 
    'D': {'D1':'unavailable', 'D2':'available', 'D3':'available'} } 

rowChoice = raw_input('What row? >> ') 
numSeats = input('How many Seats? >> ') 

Я очень новичок в этом, так что я действительно нужен очень простой метод, и, возможно, аннотацию или объяснения, как это работает.

ответ

3

Я хотел бы использовать следующее заявление для подсчета значений каждого вложенного словаря:

{k: sum(1 for val in v.itervalues() if val == 'available') for k, v in seats.iteritems()} 

Это создает новый словарь с теми же ключами, как seats с каждым значением является количество доступных мест. sum(..) с генераторным трюком эффективно подсчитывает все значения содержащегося в словаре строк, где значение равно 'available'.

Результат:

{'A': 2, 'C': 2, 'B': 2, 'D': 2} 

Показать доступные места для конкретной строки фильтровать и просто использовать len():

row_available = [k for k, v in seats[rowChoice].iteritems() if v == 'available'] 
avail_count = len(row_available) 
if avail_count: 
    print 'there {is_are} {count} seat{plural} available in row {rowChoice}, seat{plural} {seats}'.format(
     is_are='are' if avail_count > 1 else 'is', count=avail_count, 
     plural='s' if avail_count > 1 else '', rowChoice=rowChoice, 
     seats=row_available[0] if avail_count == 1 else ' and '.join([', '.join(row_available[:-1]), row_available[-1]])) 

Для rowChoice = 'A' Печатается:

there are 2 seats available in row A, seats A1 and A3 

но он регулирует для формирования когерентных предложений для большего количества мест.

+0

'сумма (значение == 'доступен' для Валу в v.itervalues ​​())' также работает как булевы суммируются, как и ожидалось (True является 1, ЛОЖЬ 0). Эпическое сохранение 5 символов –

+0

@RobCowie: я избегаю этого синтаксиса; тот факт, что 'bool' являются подклассом' int', вызывают даже опытных программистов Python и делают код менее «grokable» в моем опыте. –

+0

@RobCowie подход «1 для ...», безусловно, более явный, и если вы имеете дело с пользовательскими классами, вполне возможно, что '__eq__' может возвращать объекты, кроме« True »и« False »... (попробуйте создать ваш собственный класс с '__eq__', который только возвращает 100 ....) –

3

collections.Counter Использование и itertools.chain:

from collections import Counter 
from itertools import chain 

print Counter(chain.from_iterable(i.itervalues() for i in seats.itervalues())) 
# Counter({'available': 8, 'unavailable': 4}) 
+0

Не могу заставить его работать на меня. Я получаю 'ERROR: root: 'int' объект не имеет атрибута 'itervalues''. Также я хотел бы подсчитать 3 объекта в значениях словаря (sub). есть идеи? –

Смежные вопросы