В чем может быть проблема, с постановлением данным?
Всем привет, подскажите пожалуйста из-за чего может быть проблема? Я получил данные список словарей. Это avg_2 и avg_1, и теперь мне надо найти общие значение и добавить к общим Client. Так как у них одинаковые значение у description и Name. Она работает на половину. Половина правильно а другую половину сопоставляет не правильно.
Есть ли аналог данного кода или решить как-то по-другому ?
Пример входных данных(их более 20к поэтому ток часть могу показать):
avg_1=[
{
"Name": "alex1",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
},
{
"Name": "alex2",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
},
{
"Name": "alex3",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
}]
avg_2=
[
{
"Client": [
"Max",
"San"
],
"description": "alex3"
},
{
"Client": [
"Aro"
],
"description": "alex2"
},
{
"Client": [
"Loli"
],
"description": "alex4"
},
{
"Client": [
"Frank"
],
"description": "alex1"
}]
def workerss(Awes, names):
workers_lists = []
for miners in Awes:
workers_lists.append(miners[names])
return workers_lists
def intersection_lists(list3, list4):
return set(list3).intersection(list4)
Awe_3_wk = workers(avg_1,'Name')
Awe_4_wk = workers(avg_2,'description')
common_workerss = intersection_lists(Awe_3_wk, Awe_4_wk)
for miner_3 in avg_1:
if miner_3["Name"] in common_workerss:
for miner_4 in avg_2:
if miner_4['description'] in miner_3['Name']:
miner_3['Client'] = miner_4['Client']
result = [
{
"Name": "alex1",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
"Client": [
"Frank"
],
},
{
"Name": "alex2",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
"Client": [
"Aro"
]
},
{
"Name": "alex3",
"Object": "",
"Ip": "",
"Status": "",
"Mac": "",
"Sn": "",
"Client": [
"Max",
"San"
]
}]
Во время дэбага отрабатывает все как надо :(
Ответы (3 шт):
Всё это можно сделать намного проще.
- Создаём вспомогательный словарь:
desc_client = {d['description']: d['Client'] for d in avg_2} - Бежим по списку
avg_1, копируем словарь, чтобы исходные данные не поменялись. Добавляем пару из вспомогательного словаря.
res = []
for d in avg_1:
new_d = dict(d)
try:
new_d['Client'].extend(desc_client[new_d['Name']])
except KeyError:
try:
new_d['Client'] = desc_client[new_d['Name']]
except KeyError:
pass
res.append(new_d)
Возможные сокращения кода при соблюдении условий входных данных:
- Если гарантируется, что не будет дублей
descriptionвavg_2-try.. exceptзаменяем на этот:
try:
new_d['Client'] = desc_client[new_d['Name']]
except KeyError:
pass
- Если гарантируется наличие каждого
Nameвavg_2-try.. exceptнам не нужен, меняем на это:
new_d['Client'] = desc_client[new_d['Name']]
Возможное сокращение кода если список avg_1 можно менять и использовать как результат "вычислений-преобразований":
for d in avg_1:
d['Client'] = desc_client[d['Name']] # тут вставить нужный вариант с try.. except
На тему "по другому"
from dataclasses import dataclass, field, asdict
avg_1=[{"Name":"alex1","Object":"","Ip":"","Status":"","Mac":"","Sn":"",},{"Name":"alex2","Object":"","Ip":"","Status":"","Mac":"","Sn":"",},{"Name":"alex3","Object":"","Ip":"","Status":"","Mac":"","Sn":"",}]
avg_2=[{"Client":["Max","San"],"description":"alex3"},{"Client":["Aro"],"description":"alex2"},{"Client":["Crawl"],"description":"alex2"},{"Client":["Loli"],"description":"alex4"},{"Client":["Frank"],"description":"alex1"}]
@dataclass()
class Workers:
Name: str
Object: str
Ip: str
Status: str
Mac: str
Sn: str
Clients: list = field(default_factory=lambda: [])
def __eq__(self, other):
return self.Name == other.description
@dataclass()
class ClientList:
Client: list
description: str
def __eq__(self, other):
if key := (self.description == other.Name):
other.Clients += self.Client or []
return key
c = [ClientList(**item) for item in avg_2]
w = [k for item in avg_1 if c.count(k := Workers(**item))]
print(
*[asdict(
item
) for item in w],
sep='\n'
)
# {'Name': 'alex1', 'Object': '', 'Ip': '', 'Status': '', 'Mac': '', 'Sn': '', 'Clients': ['Frank']}
# {'Name': 'alex2', 'Object': '', 'Ip': '', 'Status': '', 'Mac': '', 'Sn': '', 'Clients': ['Aro', 'Crawl']}
# {'Name': 'alex3', 'Object': '', 'Ip': '', 'Status': '', 'Mac': '', 'Sn': '', 'Clients': ['Max', 'San']}
как альтернативный вариант можно попробовать pandas, на большом наборе данных его использование вполне оправдано:
import pandas as pd
df_1 = pd.DataFrame(avg_1)
df_2 = pd.DataFrame(avg_2).rename(columns={'description':'Name'})
res = df_1.merge(df_2,how='left').agg(dict,axis=1).tolist()
>>> res
'''
[{'Name': 'alex1',
'Object': '',
'Ip': '',
'Status': '',
'Mac': '',
'Sn': '',
'Client': ['Frank']},
{'Name': 'alex2',
'Object': '',
'Ip': '',
'Status': '',
'Mac': '',
'Sn': '',
'Client': ['Aro']},
{'Name': 'alex3',
'Object': '',
'Ip': '',
'Status': '',
'Mac': '',
'Sn': '',
'Client': ['Max', 'San']}]