遍历字典列表,并在Python中识别字典中的类似值



假设我有一个字典列表,如下

[{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2']}, {'name': 'User_ORDERS1235', 'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 'users': ['User_1']}, {'name': 'User_ORDERS1236', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_3']}]

在迭代这个列表时,我想检查表达式(键(a子列表值是否与其他字典键表达式值集相同。在上述情况下,值为User_2的users键与User_3具有相同的表达式值。在这种情况下,我想删除User_3的整个字典,并将值User_3添加到User_2列表中(作为'users':['User_2','User_3'](

表示输出:

[{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2','User_3']}, {'name': 'User_ORDERS1235', 'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 'users': ['User_1']}]
orders = [{
'name': 'User_ORDERS1234',
'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}],
'users': ['User_2']
},{
'name': 'User_ORDERS1235',
'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}],
'users': ['User_1']
},{
'name': 'User_ORDERS1236',
'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}],
'users': ['User_3']
}]
for i, order in enumerate(orders):                # loop trough orders:
exp1 = order['expressions']                   # 'exp' value of the order
for next_order in orders[i+1:]:               # loop through the next orders:
exp2 = next_order['expressions']          # 'exp' value of a next order
if exp1 == exp2:                          # if the 'exp' values are the same:
order['users'] += next_order['users'] # add the 'users' to the order 'users'
next_order['users'] = []              # remove users from the next order
orders = [o for o in orders if o['users']]        # leave only the orders that have 'users'
print(orders)

输出

[{
'name': 'User_ORDERS1234',
'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}],
'users': ['User_2', 'User_3']
},{
'name': 'User_ORDERS1235',
'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}],
'users': ['User_1']
}]

您可以使用enumerate来获取订单列表中每个订单的索引和值。scanned_exp是一个以唯一表达式为关键字的字典,该值是第一次出现唯一表达式的顺序列表中的索引。迭代时,我们检查当前表达式是否已被扫描,即在scanned_exp中。如果已经找到了,我们用当前表达式中的用户列表扩展该表达式第一次出现的索引位置处的用户列表。然后,我们使用remove从列表中删除当前订单。

scanned_exp = {}
for idx, order in enumerate(d):
exp = order["expressions"][0]["exp"]
if exp in scanned_exp:
d[scanned_exp[exp]]["users"].extend(order["users"])
d.remove(order)
else:
scanned_exp[exp] = idx

然后您的输出变为:

[
{
'name': 'User_ORDERS1234', 
'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 
'users': ['User_2', 'User_3']
}, 
{
'name': 'User_ORDERS1235', 
'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 
'users': ['User_1']
}
]

编辑

好吧,让我们把这个动态化。首先,字典的键不能是列表(不可更改类型(,所以这破坏了我们最初的实现。在上面能够用作密钥的集合是tuple(除非tuple包含不可更改的类型,即listdict(。我们可以做的是制作一个tuple,它包含作为值出现在exp键中的所有字符串值。

所以,你可以替换这个:

exp = order["expressions"][0]["exp"]

这个:

exp = tuple(e["exp"] for e in order["expressions"])
def function_1(values):
for j in range(len(values)):
for k in range(j + 1, len(values)):
if values[j]['expressions'] == values[k]['expressions']:
values[j]['users'] = values[j]['users'] + values[k]['users'] 
return values

#在性能

list_values = [{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2']}, {'name': 'User_ORDERS1235', 'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 'users': ['User_1']}, {'name': 'User_ORDERS1236', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_3']}]

#调用函数

function_1(list_values)
[{'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}],
'name': 'User_ORDERS1234',
'users': ['User_2', 'User_3']},
{'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}],
'name': 'User_ORDERS1235',
'users': ['User_1']},
{'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}],
'name': 'User_ORDERS1236',
'users': ['User_3']}]
[ ]
dictt = [{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2']}, {'name': 'User_ORDERS1235', 'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 'users': ['User_1']}, {'name': 'User_ORDERS1236', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_3']}]

def sorting_it(d):
for n,c in enumerate([x['expressions'] for x in dictt]):
if c == d['expressions'] and dictt[n] != d and d['users']:
d['users'] = d['users'] + dictt[n]['users']
del dictt[n]
f = list(map(sorting_it,dictt))
print(dictt)
>>> [{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2', 'User_3']}, {'name': 'User_ORDERS1235', 'expressions': [{'exp': '"table"."ORDERS"."STATUS"  = 'Shipped''}], 'users': ['User_1']}]

说明:

f = list(map(sorting_it,dictt))

使用map函数,dictt中的每个字典都通过函数sorting_it,每次一个作为变量d,因此第一个是:

{'name': 'User_ORDERS1234', 'expressions': [{'exp': '"table"."ORDERS"."STATUS" IN ('Canceled','Pending')'}], 'users': ['User_2']}

现在我循环遍历关键字'expressions'的值,[x['expressions'] for x in dictt]是这个的列表

如果dicttd中的关键字'expressions'的值等于[x['expressions'] for x in dictt]中关键字'expressions'的值,那么我得到索引n,用它在dictt中找到相应的字典,并将关键字'expressions'的所有值加在一起。

然后我执行del dictt[n],因为该字典的用户已经被添加到另一个字典中,所以在这种情况下,'user_3'的字典被删除,因为它们被添加到'user_2'的字典中。

此外,dictt[n] != d and d['users']确保我不会比较同一本词典。

最新更新