合并按键值分组的Python列表

时间:2017-03-18 17:08:13

标签: python python-2.7

我想在id上合并两个dicts。 Dict x包含许多不同的id和每个id的不同行数。 Dict y包含多个键值,并且总是比dict x少。

x = [{'costgroup': '1', 'POC1': '2', 'post': '5','id': '1'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '1'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '1'},
    {'costgroup': '1', 'POC1': '2', 'post': '5','id': '2'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '2'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2'}] 


 y = [{'id': '1', 'laminate': 'D'}, 
     { 'id':'2', 'laminate': T'}]       

我想要的输出如下:

z = [{'costgroup': '1', 'POC1': '2', 'post': '5','id': '1','laminate':'D'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '1','laminate': 'D'},
   {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '1','laminate': 'D'},
   {'costgroup': '1', 'POC1': '2', 'post': '5','id': '2','laminate': 'T'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '2','laminate': 'T'},
   {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2','laminate': 'T'},
   {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2','laminate': 'T'}] 

使用pandas

很容易实现
dfx  = pd.DataFrame(x)
dfy  = pd.DataFrame(y)
pd.merge(dfx,dfy, how ='left', left_on = 'id', right_on = 'id' )

但是,我将使用AWS Lambda函数应用它,我不希望有pandas的开销,输出需要是dict。我尝试下面的代码让我更接近,但后来我不得不添加一些东西来找到ID的不同值并迭代它们。但是,仍然没有我需要的输出。

valuelist = ['1']
def copyf(dictlist, key, valuelist):
      return [d for d in dictlist if d[key] in valuelist]

y1 = copyf(y, 'id', valuelist)
x1 = copyf(x, 'id', valuelist)
y1.append(x1)

上面提供了这个输出,这很有趣,但不是我需要的。

[{'distance': '2', 'id': '1', 'laminate': 'D'},
 [{'POC1': '2', 'costgroup': '1', 'id': '1', 'post': '5'},
  {'POC1': '1', 'costgroup': '2', 'id': '1', 'post': '4'},
  {'POC1': '5', 'costgroup': '3', 'id': '1', 'post': '2'}]]

3 个答案:

答案 0 :(得分:2)

ggplot(data_melt, aes(x=variable, y=value)) +
  geom_point(aes(color = time_group)) + 
  facet_grid(facet_group ~ .) +
  geom_segment(data = data_cast, aes(x = variable, xend = variable, 
                                     y = before, yend = after), 
               arrow = arrow(), 
               colour = "#FF3EFF", 
               size = 1.25)

这会产生

import copy

x = [{'costgroup': '1', 'POC1': '2', 'post': '5','id': '1'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '1'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '1'},
    {'costgroup': '1', 'POC1': '2', 'post': '5','id': '2'},
    {'costgroup': '2', 'POC1': '1', 'post': '4','id': '2'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2'},
    {'costgroup': '3', 'POC1': '5', 'post': '2', 'id': '2'}]


y = [{'id': '1', 'laminate': 'D'},
     { 'id':'2', 'laminate': 'T'}
]

#create the id->laminate mapping
m = { d['id']: d['laminate'] for d in y }

#create the final output
z = []
for d in x:
    #make a copy of the dictionary from x so that the input data
    #is not overwritten
    item = dict(d) #copy.deepcopy(d)
    item.update({'laminate': m[d['id']]})
    z.append(item)

print(z)

答案 1 :(得分:2)

def merge(d1, d2):
    """Given two dicts, merge them into a new dict as a shallow copy."""
    result = d1.copy()
    result.update(d2)
    return result

result = [merge(d1, d2) for d1 in x for d2 in y if d1["id"] == d2["id"]]
print(result)

给出

[{'POC1': '2', 'costgroup': '1', 'id': '1', 'laminate': 'D', 'post': '5'},
 {'POC1': '1', 'costgroup': '2', 'id': '1', 'laminate': 'D', 'post': '4'},
 {'POC1': '5', 'costgroup': '3', 'id': '1', 'laminate': 'D', 'post': '2'},
 {'POC1': '2', 'costgroup': '1', 'id': '2', 'laminate': 'T', 'post': '5'},
 {'POC1': '1', 'costgroup': '2', 'id': '2', 'laminate': 'T', 'post': '4'},
 {'POC1': '5', 'costgroup': '3', 'id': '2', 'laminate': 'T', 'post': '2'},
 {'POC1': '5', 'costgroup': '3', 'id': '2', 'laminate': 'T', 'post': '2'}]

从此处合并功能:How to merge two Python dictionaries in a single expression?

在Python 3.5中有一个更简洁的语法,但你在2.7上。

答案 2 :(得分:1)

z = []
for dx in x:
    for dy in y:
        if dx['id'] == dy['id']:
            z.append(dict(dx.items () + dy.items()))

print z