在python中优化访问dicts

时间:2017-06-03 19:51:18

标签: python dictionary

首先要做的事情: Python 3.5 以及下一个库:json,urllib,来自urllib导入请求

我一直试图以两种不同的方式(到目前为止)完成某些事情,我发现两者都有问题。谁能告诉我你会怎么编码呢?

代码需要使用GuildWars2的API翻译下一个词典列表中的信息,以获取每个对象的名称和位置。

ids = [{'traits': [1451, 1338, 1437], 'id': 4}, {'traits': [1471, 1482, 1711], 'id': 11}, {'traits': [2049, 2011, 1928], 'id': 18}]

首先尝试:(这很有效,此帖后面有一张图片显示结果。但是,这里的问题是它向服务器创建了12个请求,并等待要回答的时间比它应该花费的时间多。这些服务器上的每分钟请求数上限,所以我想用最少的代码对其进行编码。

specializations_items = []
for i in ids:
    webpage_stored = request.urlopen("https://api.guildwars2.com/v2/specializations/"+str(i['id'])+"?lang=es").read().decode('utf8')
    api_specialization_data = json.loads(webpage_stored)
    api_specialization_name = api_specialization_data["name"]
    translated_traits = []
    numeric_traits = []
    for j in i['traits']:
        webpage_stored = request.urlopen("https://api.guildwars2.com/v2/traits/"+str(j)+"?lang=es").read().decode('utf8')
        api_trait = json.loads(webpage_stored)
        translated_traits.append(api_trait['name'])
        for k in api_specialization_data['major_traits']:
            if j == k:
                numeric_traits.append(str(api_specialization_data['major_traits'].index(k)+1))
    numeric_traits_new = []
    for l in numeric_traits:
        l = l.replace("9", "3").replace("8", "2").replace("7", "1").replace("6", "3").replace("5", "2").replace("4", "1")
        numeric_traits_new.append(l)
    specializations_items.append("[b]"+api_specialization_name+" ("+"".join(numeric_traits_new)+"):[/b] "+", ".join(translated_traits)+".")
return "\n".join(specializations_items)

第二次尝试:(很酷,只有2个请求到服务器,但这里的问题是它是循环地狱。另外,另一个问题是我甚至不确定如何分配数字信息与每个特征的定位(该部分未完成):

# Note: Each of the next 2 vars are json.loads dicts of those websites. It's unnecesary long to paste the dicts in here, so just click on the links.
api_traits = https://api.guildwars2.com/v2/traits%3Fids=1451%2C%201338%2C%201437%2C%2C1471%2C%201482%2C%201711%2C%2C2049%2C%202011%2C%201928%26lang=es
api_specializations = https://api.guildwars2.com/v2/specializations%3Fids=4%2C11%2C18%26lang=es

numeric_traits = []
for j in api_specializations:
    for m in j['major_traits']:
        for n in api_traits:
            if n['id'] == m:
                numeric_traits.append(str(j['major_traits'].index(n['id'])+1)+n['name'])
for i in ids:
    for j in api_specializations:
        if i['id'] == j['id']:
            i['name'] = j['name']
    for k in api_traits:
        for l in i['traits']:
            if l == k['id']:
                i['traits'].remove(l)
                i['traits'].append(k['name'])
print(numeric_traits) #Not finished, I don't think using so much loops is a good idea.

期望的输出:

Desired Output

加成:

我将提供2个不同的ID,以防您想要使用不同的ID检查不同的输出:

ids = [{'traits': [296, 325, 1510], 'id': 31}, {'traits': [232, 1502, 226], 'id': 41}, {'traits': [1952, 2015, 1986], 'id': 48}]
ids = [{'traits': [815, 816, 801], 'id': 39}, {'traits': [1876, 1844, 778], 'id': 19}, {'traits': [2020, 2031, 1919], 'id': 34}]

因此...

完成我的任务的最佳方法是什么,它不会创建不必要的服务器请求,并且在没有我变得疯狂的情况下获得所需的结果,因为循环内循环内部的循环(这也很慢) ?

1 个答案:

答案 0 :(得分:1)

我使用requests库从第二个代码段中获取JSON。这是一种有效的方法:

import requests

api_traits = requests.get("https://api.guildwars2.com/v2/traits%3Fids=1451%2C%201338%2C%201437%2C%2C1471%2C%201482%2C%201711%2C%2C2049%2C%202011%2C%201928%26lang=es").json()
api_specializations = requests.get("https://api.guildwars2.com/v2/specializations%3Fids=4%2C11%2C18%26lang=es").json()

traits_dict = { trait["id"]: trait["name"] for trait in api_traits }

for specialization in api_specializations:
    numeric_traits = []
    trait_names = []
    for i, trait_id in enumerate(specialization["major_traits"]):
        if trait_id in traits_dict:
            numeric_traits.append(i % 3 + 1)
            trait_names.append(traits_dict[trait_id])
    print("{} ({}): {}.".format(specialization["name"],
                                "".join(map(str, numeric_traits)),
                                ", ".join(trait_names)))

# Output:
# Fuerza (221): Fuerza restauradora, Mandoble eficaz, Potencia berserker.
# Tácticas (333): Potenciado, Potenciar aliados, Fuerza de falange.
# Berserker (111): Pendenciero aplastante, Reacción sangrienta, Rugido sangriento.

三件重要的事情:

  1. 我制作了一个字典,将特征ID映射到特征名称。这样可以避免嵌套循环尝试匹配。
  2. 我使用enumerate来避免index查询,当您跟踪哪个特征处于哪个位置时(对于"数字特征")。
  3. 我使用模运算来帮助处理数字特征。 i % 3在除以3时得到余数(因为特征在三列中),然后+ 1只返回到基于1的索引。
  4. 如果代码中的任何其他内容令人困惑,请告诉我。