#python #json #formatting
Вопрос:
Я получаю такой ввод:
input 1:
{
"name": "Ben",
"description": "Ben",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
input 2
{
"name": "Ice",
"description": "Ice",
"attributes": [
{
"type": "Background",
"value": "Green"
},
{
"type": "Hair-color",
"value": "White"
}
]
}
input 3
{
"name": "Itay",
"description": "Itay",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
}
Что я хочу сделать, так это подсчитать количество каждого типа фона и каждого типа цвета волос, появляющихся.
(Это примерные примеры, и на самом деле существует больше типов и разных значений)
Допустим, в этих примерах у нас есть 2 объекта, у которых по умолчанию есть фон, тогда я хочу, чтобы их количество было примерно таким:
Backround default count=2
hair-color brown = 2
background green = 1
hair-color white = 1
Мне нужен наиболее эффективный код, потому что в коде есть и другие аспекты, кроме того, он будет выполняться на тысячах запросов, а не только на двух, поэтому его тоже нужно запускать в хорошие времена 😀
Мой код до сих пор:
import requests
import json
from collections import Counter
from collections import defaultdict
from time import sleep
attributes = []
test_dict = defaultdict(list)
for i in range(min_id, max_id 1):
api = 'api/v1/test/{}'.format(i)
response = requests.get(api)
item_dict = json.loads(response.text)
for item in item_dict['attributes']:
attributes.append(item["trait_type"]) if item["trait_type"] not in attributes else attributes
test_dict[item["trait_type"]].append(item["value"])
sleep(0.02)
for attribute in attributes:
print(attribute)
print(Counter(test_dict[attribute]))
Комментарии:
1. Что произошло, когда вы попытались это сделать? Как далеко вы продвинулись? В чем была проблема?
2. Я понимаю, как я могу подсчитать, сколько раз появлялся фон, цвет волос, по умолчанию, коричневый, зеленый и белый. Я не понимаю/не знаю, как связать фон с цветом по умолчанию и зеленым, а цвет волос с коричневым и белым.
3. поделитесь своим рабочим кодом
4. @Sabil у меня не так много рабочего кода, в основном это база взаимодействия с API. То, что я собираюсь сделать, — это создать словарь, подобный этому:
{backround: default, count: 2}
Но это может усложнить дальнейшее кодирование. В конце концов, я хочу рассчитать общее количество объектов (в нашем случае 3) и разделить каждое значение на общее, чтобы увидеть, какой процент от общего количества значений это.5. Я просто обновляю свой ответ, надеюсь, что он решит все ваши проблемы, включая расчет коэффициента. 🙂
Ответ №1:
Это должно сработать для вас:
def constract_data(data_dict):
output = []
total_count = 0
for data in data_dict:
attributes = data["attributes"]
for attribute in attributes:
total_count = 1
dict_key = attribute["type"].lower()
dict_value = attribute["value"].lower()
dict_index = [index for index, data in enumerate(output) if data.get(dict_key, "") == dict_value]
if dict_index:
output[dict_index[0]]['count'] = 1
else:
atb_dict = {dict_key: dict_value, 'count': 1}
output.append(atb_dict)
return output, total_count
def calculate_occurrence_ratio(data_dict, total_count):
for index, data in enumerate(data_dict):
count = data.get('count', 0)
ratio = round(((count / total_count) * 100), 2)
data['ratio'] = f'{ratio}%'
return data_dict
data_dict = [
{
"name":"Ice",
"description":"Ice",
"attributes":[
{
"type":"Background",
"value":"Green"
},
{
"type":"Hair-color",
"value":"White"
}
]
},
{
"name":"Ben",
"description":"Ben",
"attributes":[
{
"type":"Background",
"value":"Default"
},
{
"type":"Hair-color",
"value":"Brown"
}
]
},
{
"name":"Itay",
"description":"Itay",
"attributes":[
{
"type":"Background",
"value":"Default"
},
{
"type":"Hair-color",
"value":"Brown"
}
]
}
]
output_data, total_count = constract_data(data_dict)
output_data = calculate_occurrence_ratio(output_data, total_count)
print(output_data)
Выход:
[{'background': 'green', 'count': 1, 'ratio': '16.67%'}, {'hair-color': 'white', 'count': 1, 'ratio': '16.67%'}, {'background': 'default', 'count': 2, 'ratio': '33.33%'}, {'hair-color': 'brown', 'count': 2, 'ratio': '33.33%'}]
Комментарии:
1. Как вы думаете, с каким результатом будет проще работать? Твое или это:
{'background': {'green': 1, 'default': 2}, 'hair-color': {'white': 1, 'brown': 2}}
2. Это зависит от того, каким будет результат вашего желания?
3. В общем, что я хочу сделать, так это дать каждой черте оценку. Затем, если у пользователя есть определенная черта, дайте ему оценку. Поэтому в основном я хочу рассчитать редкость появления каждого пользователя с помощью оценки. Допустим, оценка за то, что цвет волос белый, равна 100, Ice получит 100 очков.
4. Ооо, тогда я должен обновить свой ответ в соответствии с вашими требованиями. 🙂
5. Хорошо, потрясающе, тай, и извини за всю суету 😀 Твой ответ потрясающий, и он все прекрасно просчитывает. тай очень сильно 😀
Ответ №2:
это решение будет работать для вас:
list_data = [
{
"name": "Ice",
"description": "Ice",
"attributes": [
{
"type": "Background",
"value": "Green"
},
{
"type": "Hair-color",
"value": "White"
},
{
"type": "other",
"value": "White"
}
]
},
{
"name": "Ben",
"description": "Ben",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
},{
"name": "Itay",
"description": "Itay",
"attributes": [
{
"type": "Background",
"value": "Default"
},
{
"type": "Hair-color",
"value": "Brown"
}
]
},
]
output = {}
all_count = {}
for user in list_data:
data = user["attributes"]
for dat in data:
typeu = dat["type"]
if typeu not in all_count:
all_count[typeu]=1
else:
all_count[typeu] =1
for user in list_data:
data = user["attributes"]
for dat in data:
typeu = dat["type"]
if typeu not in output:
output[typeu]={}
if dat["value"] not in output[typeu]:
output[typeu][dat["value"]] = "1 with: {}%".format(int(1/all_count[typeu]*100))
else:
count = int(output[typeu][dat["value"]][0]) 1
output[typeu][dat["value"]] = str(count) " with: {}%".format(int(count/all_count[typeu]*100))
print(output)
Комментарии:
1. Как я уже говорил в посте, иногда атрибутами будут не только фон и цвет волос. Сценарий должен идентифицировать их самостоятельно…
2. хорошо, я отредактировал это
3. Как вы думаете, есть ли способ также рассчитать вероятность того, что это произойдет? Так что в основном просто разделите количество каждого элемента на общее количество пользователей:
Backround default:2 66% of it occuring
4. я отредактировал его. не могли бы вы, пожалуйста, отметить это как решение?
5. Когда я помещаю это в свой код, некоторые атрибуты отображаются как 100%, некоторые нет, и общий процент не составляет 100% пример:
{'background': {'crisp green': '1 Ratio: 100%', 'dashing purple': '2 Ratio: 66%', 'spiffy blue': '1 Ratio: 25%', 'dapper cyan': '2 Ratio: 33%'}
Ответ №3:
Вот еще один подход:
from collections import defaultdict
data_dict = [
{
"name":"Ice",
"description":"Ice",
"attributes":[
{
"type":"Background",
"value":"Green"
},
{
"type":"Hair-color",
"value":"White"
}
]
},
{
"name":"Ben",
"description":"Ben",
"attributes":[
{
"type":"Background",
"value":"Default"
},
{
"type":"Hair-color",
"value":"Brown"
}
]
},
{
"name":"Itay",
"description":"Itay",
"attributes":[
{
"type":"Background",
"value":"Default"
},
{
"type":"Hair-color",
"value":"Brown"
}
]
}
]
out = defaultdict(lambda: defaultdict(int))
tot_count = defaultdict(int)
for data in data_dict:
for attri in data['attributes']:
tot_count[attri['type']] =1
out[attri['type']][attri['value']] =1
for k, v in out.items():
for k1, v1 in v.items():
print (f'{k.lower()} {k1} count={v1} ratio={int(v1*100/tot_count[k])}%')
Выход:
background Green count=1 ratio=33%
background Default count=2 ratio=66%
hair-color White count=1 ratio=33%
hair-color Brown count=2 ratio=66%