合并两个列表并创建一个新字典

时间:2016-08-30 12:36:06

标签: python list dictionary

我找不到一个很好的方法来做到这一点。假设我有两个列表(列表中包含具有给定属性的对象)。我需要使用merged atttributes创建一个新的字典/列表。

listA = [
  {
    "alpha": "some value",
    "time": "datetime",
  },
  ...
]

listB = [
  {
    "beta": "some val",
    "gamma": "some val",
    "time": "datetime"
  },
  ...
]

结果应如下(它应根据"时间"属性合并)

result = {
  "datetime": {
    "alpha": "some value",
    "beta": "some val",
    "gamma": "some val"
  },
  ...
}

我如何以python方式执行此操作?

例如,

listA = [
  {
    "time": "Jan 1",
    "alpha": "one"
  },
  {
    "time": "Jan 3",
    "alpha": "three"
  }
]

listB = [
  {
    "beta": "one-one",
    "gamma": "one-two",
    "time": "Jan 1"
  },
  {
    "beta": "two-one",
    "gamma": "two-two",
    "time": "Jan 2"
  },
]

result = {
  "Jan 1": {
    "alpha": "one",
    "beta": "one-one",
    "gamma": "one-two",
  },
  "Jan 2": {
    "beta": "two-one",
    "gamma": "two-two",
  },
  "Jan 3": {
    "alpha": "three"
  }
}

3 个答案:

答案 0 :(得分:2)

使用列表理解

由于您正在搜索不使用for循环的替代方法,因此这是一个使用list comprehensions的实现,这会导致双线性。我不确定这是否比for循环更直观:

output = {}
[output.setdefault(item["time"],{}).update({key: value}) 
 for key, value in item.items()     
 if key != "time" 
 for item in (listA + listB)]

对我而言,这只是一种更复杂的for循环方式...... setdefault的文档。

使用经典for循环

使用示例中提供的listAlistB

combined = listA + listB

merged = {}
for item in combined:
    time = item["time"]
    # setdefault only acts if the key is not found, initiate a dict then
    merged.setdefault(time, {})
    for key, value in item.items():
        if key != "time":
            merged[time].update({key: value})

print merged

输出:

{'Jan 2': {'beta': 'two-one', 'gamma': 'two-two'}, 'Jan 3': {'alpha': 'three'}, 'Jan 1': {'alpha': 'one', 'beta': 'one-one', 'gamma': 'one-two'}}

答案 1 :(得分:1)

另一个答案,那可能更清晰,因为它避免了有利于dict方法的条件测试,只使用了一个级别的缩进:

d={}

for e in listA:
    t = e["time"]
    d.setdefault(t, {}).update(**e)

for e in listB:
    t = e["time"]
    d.setdefault(t, {}).update(**e)

# get rid of "time" keys, if important to do so

for e in d.values():
    del e["time"]
如果d.setdefault(t, {})中尚未显示密钥d[t],则

t会将d创建为空字典,并返回d[t]。然后.update(**e)更新返回的dict以包含e中的所有键和值(如果它们存在则替换当前值,这可能是错误或功能 - 示例没有任何重叠或说明应该是什么如果有重叠就会发生)

答案 2 :(得分:0)

这段代码可能是一个好的开始:

listA = [
  {
    "time": "Jan 1",
    "alpha": "one"
  },
  {
    "time": "Jan 3",
    "alpha": "three"
  }
]

listB = [
  {
    "beta": "one-one",
    "gamma": "one-two",
    "time": "Jan 1"
  },
  {
    "beta": "two-one",
    "gamma": "two-two",
    "time": "Jan 2"
  },
]
result = {}

# We consider every element of A and B one by one
for elem in listA + listB:
    key = elem["time"]

    # If that is the first time we encounter that key, we create a new empty dict in result
    if not result.get(key, None):
        result[key] = {}

    # We copy the content of the elem in listA or listB into the right dictionnary in result.
    for dictKey in elem.keys():

        # We don't want to copy the time
        if dictKey == "time":
            continue
        result[key][dictKey] = elem[dictKey]
print(result)