【问题标题】:Intersect a list of dicts based on a common key基于公共键与字典列表相交
【发布时间】:2011-06-03 02:27:43
【问题描述】:

假设我有两个字典列表:

dates = [{'created':'2010-12-01'},{'created':'2010-12-02'},....]
elts = [{'created':'2010-12-01', 'key1':'val1', 'key2':'val2'}, {'created':'2010-12-05','key1':'val1'}]

日期列表是一堆连续的日期。

elts 列表可以是从 1 到 len(dates) 的任何位置,而我想要做的基本上是填充 elts,这样无论是否有其他键,它都有一个日期的字典。

这是我幼稚的解决方案:

for d in dates:
    for e in elts:
        if d['created'] == e['created']:
            d.update(dict(key1=e['key1']))

因此,我将有一个最终的array d,每个dict 中都有所有日期,但可能/可能没有其他键/val。

什么是好的“pythonic”解决方案?

【问题讨论】:

  • 听起来你真正想要的是一个 dicts 的 dict,外层的 dict 以“创建”日期为键。
  • d.update(dict(key1=e['key1'])) 是一种奇怪的写法d['key1']=e['key1']

标签: python list intersection


【解决方案1】:

我认为您的问题有点不对劲,因为您的解决方案似乎并没有真正解决您的问题,但是如果您想为 dates 中的每个日期在 elts 中创建一个尚未出现的条目在elts,你可以使用这个:

all_dates = set(e['created'] for e in dates) # gets a list of all dates that exist in `dates`
elts_dates = set(e['created'] for e in elts) # same for elts

missing_dates = all_dates - elts_dates

for entry in missing_dates:
    elts.append(dict(created=entry))

这是一个http://codepad.orgsn-p,它显示了这个sn-p的效果:http://codepad.org/n4NbjvPM

【讨论】:

  • +1,这也是我对这个问题的理解。 set() 可以很好地与生成器表达式配合使用,因此使用 set(e['created'] for e in dates) 等会更有效。
  • @gnibbler:好点子。我更新了我的答案以使用生成器表达式(并更新了键盘 sn-p 以使用新的更改)
【解决方案2】:

编辑:不同的解决方案:

制作一组你已经得到的日期:

dates_in_elts = set(e['created'] for e in elts)

for d in dates:
    if d['created'] not in dates_in_elts:
        e.append(d)

这只会对每个列表进行一次迭代,而不是对日期中的每个日期迭代 elts。

【讨论】:

  • 我建议不要使用 set(),因为它不会将键和值保留在一起。
  • @lshpecK:如果您想让它们保持最新状态,那么最好将它们放在一起。但是,如果您立即创建并使用它,那么一套绝对可以正常工作。
【解决方案3】:

我可能会改用这些列表字典。

  dates_d = dict([(x['created'], x) for x in dates])
  elts_d = dict([(x['created'], x) for x in elts])
  dates_d.update(elts_d)

如果你需要它再次成为一个字典列表,你可以很容易地做到这一点:

  dates = [dates_d[x] for x in sorted(dates_d)]

如果您除了合并它们之外没有做任何其他事情,那么您的解决方案可能更容易阅读。但我怀疑,在这种情况下,字典列表并不是一种非常方便的数据格式。

【讨论】:

    【解决方案4】:

    也许我读错了,但在我看来,您的代码的最终结果是,对于 elts 中的每个 dict,您真的只想从 elts 复制该 dict 以覆盖日期中的相应 dict。

    >>> for d in dates:
    ...    for e in elts:
    ...       if d['created'] == e['created']:
    ...          d.update(e)
    

    那时,正是 dates 字典反映了我认为你想要什么。

    【讨论】:

    • 那是正确的,日期反映之后我只是这样做,elts = dates 并使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 2014-10-13
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    相关资源
    最近更新 更多