【问题标题】:How to return dictionary for longest list of dicts containing an item belonging to multiple list of dicts?如何返回包含属于多个字典列表的项目的最长字典列表的字典?
【发布时间】:2016-06-20 23:49:33
【问题描述】:

真的很难说出这个问题,而且我也很难解决如何解决这个问题。 假设我有以下字典。

mydict = { u'10441':
             [{u'quantity':   1, u'productId': 10441},
              {u'quantity':  25, u'productId': 10451},
              {u'quantity': 100, u'productId': 10461}],
           u'10451':
             [{u'quantity':   1, u'productId': 10451},
              {u'quantity':   4, u'productId': 10461}]
          }

如何返回最大的顶级子字典,该字典具有与其他字典相同的 productId 值?例如 productId 10461 存在于 mydict 的两个字典(10441 和 10451)中。我想以编程方式获取以下内容,因为此 dict (10441) 的值包含三个项目 (dicts)。

mydict1 = { u'10441':
             [{u'quantity':   1, u'productId': 10441},
              {u'quantity':  25, u'productId': 10451},
              {u'quantity': 100, u'productId': 10461}]
          }

通常我能够解决这类问题,但由于某种原因,我遇到了这个问题。有没有办法以惯用的方式解决这个问题,可能使用过滤器或嵌套的字典理解?

【问题讨论】:

  • 据我了解,您首先需要计算每个字典的常用项数,并在计算时记住哪个字典最常用(您需要一个最大值,某种索引来记住哪个 dict 是选择的,一个 maxNumberOfItems)。在检查 dictA 是否有比 max 更多的常见项目时,请确保您还检查是否相等。如果它们具有相同数量的公共项目,则更新索引和 maxNumberOfItems。
  • 您是否在寻找特定的产品 ID(即您将提供 10461)?还是要检查 all 产品字典中的 all 产品 ID?
  • 不是特定的 ID。有很多(超过一千个 productId),我想通过在每个上运行比较逻辑来获得最大尺寸的字典。

标签: python list dictionary


【解决方案1】:

在您的示例中只有两个顶级词典,很难看出您真正追求的是什么。我们在谈论多少个顶级词典?他们中有多少人必须共享一个 ID?让我们看看您如何通过成对比较有效地做到这一点,希望您知道从那里去哪里。

首先,为每个顶级字典中的 Id 创建一个索引(一组)。

myindex = dict()
for k, vals in mydict.items():
    myindex[k] = set(d["productId"] for d in vals)

现在我们将比较索引。要查看两个字典是否有共同的 ID,请取它们的交集:

mydict1 = dict()
for key1, key2 in itertools.combinations(mydict, 2):
    if myindex[key1].intersection(myindex[key2]):
        bigkey = key1 if len(mydict[key1]) > len(mydict[key2]) else key2
        mydict1[bigkey] = mydict[bigkey]

【讨论】:

  • 抱歉,Alexis 没有提供足够的上下文。将有数量不确定的字典,所有这些字典都将具有上述相同的结构。我只给出了其中两个,但会有更多不同的 productId。我会采纳你的建议并尝试一下。感谢您的帮助。
  • 谢谢,我想通了,但是您如何处理多个字典之间的重叠?如果一个 Id 出现在字典 A、B 和 C 中(这会给你三个成对的重叠),你会怎么做?我只比较对,因为这是您的问题描述的唯一场景。
  • 我实际上有同样的问题,并意识到一旦我尝试了你的代码。我可能需要比较可能的 3 对场景,但仅此而已。我倾向于 Brendan 上面在 try 块中提供的解决方案,只要我有用作过滤器的 productId,它应该考虑任意数量的字典。
  • 当然,如果它有效,那就去做吧。为使用每个产品 ID 的所有内容创建反向索引很简单,但如果您已经有可用的解决方案,我不会打扰。
【解决方案2】:

你可以这样做。 try/except 仅在 none id 列表包含给定产品 id 的情况下存在(这将导致 max 由于空序列而引发 ValueError)。

当您的产品词典中的多个项目包含相同数量的项目时(即有不止一个“最长”词典),答案有些模糊。

pid = 10461

try:
    mid, mlist = max(((id, dlist) for id, dlist in mydict.iteritems() if any(d['productId'] == pid for d in dlist)), key=lambda x: len(x[1]))
    mdict1 = {mid: mlist}
except ValueError:
    mdict1 = None

【讨论】:

    【解决方案3】:

    使用 id2parents 跟踪每个产品 ID 的父 ID。对于任何具有与mydict 中元素数量相同数量的父项的产品ID,它必须存在于每个目录中。将这样的目录id收集到parent_ids,并按大小排序,选择第一个:

    mydict = { u'10441':
            [{u'quantity':   1, u'productId': 10441},
                {u'quantity':  25, u'productId': 10451},
                {u'quantity': 100, u'productId': 10461}],
            u'10451':
            [{u'quantity':   1, u'productId': 10451},
                {u'quantity':   4, u'productId': 10461}]
            }
    
    id2parents = {}
    for parent_id, subdirs in mydict.iteritems():
        for d in subdirs:
            id2parents.setdefault(d['productId'], []).append(parent_id)
    
    parent_ids = []
    for product_id, dirs in id_dirs.iteritems():
        if len(dirs) == len(mydict.values()):
            parent_ids += dirs
    
    parent_ids.sort(key=lambda parent_id: len(mydict[parent_id]), reverse=True)
    mydict1 = mydict[parent_ids[0]]
    print mydict1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多