【问题标题】:Extracting elements from two lists of dicts if other elements match using comprehension如果其他元素使用理解匹配,则从两个字典列表中提取元素
【发布时间】:2018-11-21 13:52:02
【问题描述】:

如何遍历两个字典列表,通过键匹配列表之间的字典,如果匹配,则将每个字典中的特定键附加到新字典中的键值对中。让我用一个例子来澄清一下:

l1 = [{'id': 52, 'email': 'someemail@yahoo.com', 'anotherfield': 'some value'},
       .....
      {'id': 98, 'email': 'anotheremail@yahoo.com', 'anotherfield': 'another value'}]

l2 = [{'id': 93, 'email': 'someemail@yahoo.com', 'another key': 'seventeen'},
       .....
      {'id': 101, 'email': 'anotheremail@yahoo.com', 'another key': 'twenty'}]


# match the 'email' keys between each list, and if match, create k, v pair from id's

desired_output = {'52': 93.....'98': 101}

我可以很容易地通过简单地遍历每个列表来实现这一点,如下所示:

lookup = dict()
for l in l1:
    for p in l2:
        if l['email']==p['email']:
            lookup[l['id']]=p['id']
            break

但是这有点笨拙,我更喜欢某种理解。我的尝试:

lookup = {k['id']: v['id'] for k, v in zip(l1, l2) if k['email'] == v['email']}

【问题讨论】:

  • 你的 for 循环很好。但是,如果您要使用理解,则需要{... for l in l1 for p in l2 if l['email']==p['email']} 注意它如何与您的 for 循环对齐。但是,您将无法打破,这使得这不太理想。无论如何,有比蛮力检查更好的算法,所以,我宁愿改变 那个 而不是从完美的 for 循环转换为理解。
  • 有趣,您能否提供完整的行以及您的建议编辑?
  • {l['id']:p['id'] for l in l1 for p in l2 if l['email']==p['email']}
  • 这非常有效,感谢您的帮助,我会看看其他可能更强大的方法。再次感谢。
  • 列表中元素的顺序是否一致?如果不是,则算法不起作用。 if k['email'] == v['email'] 将工作,然后 k[N] == v[N]。您需要由列表组成,并在运行您的解决方案时。或者,您可以从列表中创建一个字典:d = defaultdict(list)d[email].append(id)

标签: python dictionary list-comprehension


【解决方案1】:

试试这个:

from itertools import product
lookup = {k['id']: v['id'] for k, v in product(l1, l2) if k['email'] == v['email']}

【讨论】:

  • 这绝对有效,所以谢谢。有没有不涉及导入附加模块的解决方案?
  • 导入itertools并没有太多的成本。但回答你的问题应该说是的。但是您应该自己实现产品(将两个列表中的所有项目匹配在一起)
【解决方案2】:

不一致列表的解决方案:

l1 = [{"email": "email1", "id": 1}, {"email": "email2", "id": 2}, {"email": "email3", "id": 3}]
l2 = [{"email": "email2", "id": 22}, {"email": "email4", "id": 4}, {"email": "email1", "id": 11}, ]

emails = {}
lookup = {}

for el in l1:
    emails[el["email"]] = el["id"]

for el in l2:
    email = el["email"]
    if email in emails:
        lookup[emails[email]] = el["id"]

# {1: 11, 2: 22}
print(lookup)

# bad solution from question
lookup = {k['id']: v['id'] for k, v in zip(l1, l2) if k['email'] == v['email']}

# {} - empty
print(lookup)

如果您需要更多列表 - 扩展解决方案,请在 finally 循环之前更新所有循环的电子邮件字典

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 2023-01-26
    相关资源
    最近更新 更多