【问题标题】:Python dictionaries, find similaritiesPython 字典,寻找相似之处
【发布时间】:2011-01-25 18:40:09
【问题描述】:

我有一个包含一千个项目的 python 字典。每个项目本身就是一本字典。我正在寻找一种简洁优雅的方式来解析每个项目,并查找和创建模板。

以下是单个字典结构的简化示例:

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

由此,我想通过一次,如果 1000 个中的 500 个共享相同的高度和宽度,请确定这一点,以便我可以根据该数据构建一个模板,并将模板 ID 分配给“模板”。我可以构建一个巨大的参考哈希,但我希望有一种更简洁、更优雅的方式来完成它。

实际数据包括接近 30 个键,其中一小部分需要从模板检查中排除。

【问题讨论】:

    标签: python templates dictionary templating


    【解决方案1】:

    给定字典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)
    

    【讨论】:

    • 在groupby之前需要一轮排序,因为groupby只会对具有相同key的连续项进行分组。
    【解决方案2】:

    @eumiro 有一个非常棒的核心思想,即使用itertools.groupby() 将具有共同值的项目批量排列在一起。但是,除了忽略首先使用 @Jochen Ritzel 指出的相同键功能(并且在文档中也提到)对事物进行排序之外,他也没有解决您提到的其他几件想要做的事情。

    以下是更完整且更长的答案。它确定模板并一次性将它们分配给 dict-of-dicts。为此,首先创建一个排序的项目列表后,它使用groupby() 对它们进行批处理,如果每个组中有足够的数量,则创建一个模板并将其 ID 分配给每个成员。

    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)}
    

    【讨论】:

    • 优秀。我正在根据第一个响应总结一些概念验证代码,但是您的回答解决了我遇到的一些问题。谢谢。喜欢这个地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 2015-06-09
    • 1970-01-01
    • 2011-12-12
    • 2021-04-30
    • 2019-09-20
    • 1970-01-01
    相关资源
    最近更新 更多