Словари Python, найти сходства - PullRequest
1 голос
/ 25 января 2011

У меня есть словарь Python с тысячей предметов.Каждый элемент сам по себе является словарем.Я ищу чистый и элегантный способ разбора каждого элемента, а также поиска и создания шаблонов.

Вот упрощенный пример структуры отдельных словарей:

{'id': 1,
 'template': None,
 'height': 80,
 'width': 120,
 'length': 75,
 'weight': 100}

Из этогоЯ хочу пройти один раз, и если 500 из 1000 будут иметь одинаковую высоту и ширину, определите это, чтобы я мог построить шаблон на основе этих данных и назначить идентификатор шаблона для «шаблона».Я могу создать гигантский эталонный хеш, но я надеюсь, что есть более чистый и элегантный способ сделать это.

Фактические данные включают ближе к 30 ключам, из которых небольшое подмножество необходимо исключить из шаблона.проверка.

Ответы [ 2 ]

3 голосов
/ 25 января 2011

Учитывая диктовку диктов items:

import itertools as it

for (height, width), itemIter in it.groupby (items.values(), lambda x: (x['height'], x['width'])):
    # in list(itemIter) you will find all items with dimensions (height, width)
0 голосов
/ 26 января 2011
У

@ eumiro была отличная основная идея, а именно идея использования itertools.groupby() для объединения элементов с общими значениями в партии.Однако, помимо того, что он пренебрег сначала сортировкой, используя ту же самую ключевую функцию, на которую указывал @Jochen Ritzel (и также упоминается в документации), он также не затронул несколько других вещей, которые вы упомянули, желая сделать.* Ниже приведен более полный и несколько более длинный ответ.Он определяет шаблоны и назначает их за один проход в зависимости от диктата.Для этого после первого создания отсортированного списка элементов он использует groupby() для их пакетной обработки, и, если их достаточно в каждой группе, создает шаблон и назначает его идентификатор каждому участнику.

inventory = {
    'item1': {'id': 1, 'template': None, 'height': 80, 'width': 120, 'length': 75, 'weight': 100},
    'item2': {'id': 2, 'template': None, 'height': 30, 'width': 40,  'length': 20, 'weight': 20},
    'item3': {'id': 3, 'template': None, 'height': 80, 'width': 100, 'length': 96, 'weight': 150},
    'item4': {'id': 4, 'template': None, 'height': 30, 'width': 40,  'length': 60, 'weight': 75},
    'item5': {'id': 5, 'template': None, 'height': 80, 'width': 100, 'length': 36, 'weight': 33}
}

import itertools as itools

def print_inventory():
    print 'inventory:'
    for key in sorted(inventory.iterkeys()):
        print '  {}: {}'.format(key, inventory[key])

print "-- BEFORE --"
print_inventory()

THRESHOLD = 2
ALLKEYS = ['template', 'height', 'width', 'length', 'weight']
EXCLUDEDKEYS = ['template', 'length', 'weight']
INCLUDEDKEYS = [key for key in ALLKEYS if key not in EXCLUDEDKEYS]

# determines which keys make up a template
sortby = lambda item, keys=INCLUDEDKEYS: tuple(item[key] for key in keys)

templates = {}
templateID = 0
sortedinventory = sorted(inventory.itervalues(), key=sortby)
for templatetuple, similariter in itools.groupby(sortedinventory, sortby):
    similaritems = list(similariter)
    if len(similaritems) >= THRESHOLD:
        # create and assign a template
        templateID += 1
        templates[templateID] = templatetuple # tuple of values of INCLUDEDKEYS
        for item in similaritems:
            item['template'] = templateID
print
print "-- AFTER --"
print_inventory()
print
print 'templates:', templates
print

Когда я запускаю его, выводится следующее:

-- BEFORE --
inventory:
  item1: {'weight': 100, 'height': 80, 'width': 120, 'length': 75, 'template': None, 'id': 1}
  item2: {'weight': 20, 'height': 30, 'width': 40, 'length': 20, 'template': None, 'id': 2}
  item3: {'weight': 150, 'height': 80, 'width': 100, 'length': 96, 'template': None, 'id': 3}
  item4: {'weight': 75, 'height': 30, 'width': 40, 'length': 60, 'template': None, 'id': 4}
  item5: {'weight': 33, 'height': 80, 'width': 100, 'length': 36, 'template': None, 'id': 5}

-- AFTER --
inventory:
  item1: {'weight': 100, 'height': 80, 'width': 120, 'length': 75, 'template': None, 'id': 1}
  item2: {'weight': 20, 'height': 30, 'width': 40, 'length': 20, 'template': 1, 'id': 2}
  item3: {'weight': 150, 'height': 80, 'width': 100, 'length': 96, 'template': 2, 'id': 3}
  item4: {'weight': 75, 'height': 30, 'width': 40, 'length': 60, 'template': 1, 'id': 4}
  item5: {'weight': 33, 'height': 80, 'width': 100, 'length': 36, 'template': 2, 'id': 5}

templates: {1: (30, 40), 2: (80, 100)}
...