It works for my game:
import random
ships = {
"transporter": {
"type": "transporter", "price": 5000
},
"scout": {
"type": "fighter", "price": 8000
},
"interceptor": {
"type": "fighter", "price": 100003
}
}
player_ship = random.choice(list(ships))
print(player_ship)
Is it possible to read key: value using input?
E.g.
player_ship = input("Choose a ship:")
and when the user enters "1" he will choose "transporter"?
Thanks for your suggestions. I feel a bit enlightened! :)
I also found a very good source:https://www.pythonpool.com/dictionary-to-list-python/
Peace to everyone!
Yes, it is possible:
userInput = int(input("Choose a ship: "))
print(ships[list(ships)[userInput-1]])
Example output #1
Choose a ship: 1
{'type': 'transporter', 'price': 5000}
Example output #2
Choose a ship: 2
{'type': 'fighter', 'price': 8000}
Note that, you have to define the ships beforehand.
With current structure you have to do what #Amirhossein suggested. However, this entails to keep another list for keys.
If you're only going to use ships for this purpose, you could write ships this way:
ships = [{"name": "transporter", "type": "transporter", "price": 5000},
{"name": "scout", "type": "fighter", "price": 8000},
{"name": "interceptor", "type": "fighter", "price": 100003}]
then:
userInput = int(input("Choose a ship: "))
print(ships[userInput - 1]['name'])
Now you can access the list container easily by index.
Try this
user_ship = int(input("Choose a ship:"))
list_of_ships = list(ships)
print(list_of_ships[user_ship - 1])
Related
I have a nested JSON data. I want to get the value of key "name" inside the dictionary "value" based on the key "id" in "key" dictionary (let the user enter the id). I don't want to use indexing which, because places are changing on every url differently. Also data is large, so I need one row solution (without for loop).
Code
import requests, re, json
r = requests.get('https://www.trendyol.com/apple/macbook-air-13-m1-8gb-256gb-ssd-altin-p-67940132').text
json_data1 = json.loads(re.search(r"window.__PRODUCT_DETAIL_APP_INITIAL_STATE__=({.*}});window", r).group(1))
print(json_data1)
print('json_data1:',json_data1['product']['attributes'][0]['value']['name'])
Output
{'product': {'attributes': [{'key': {'name': 'İşlemci Tipi', 'id': 168}, 'value': {'name': 'Apple M1', 'id': 243383}, 'starred': True, 'description': '', 'mediaUrls': []}, {'key': {'name': 'SSD Kapasitesi', 'id': 249}..........
json_data1: Apple M1
JSON Data
{
"product": {
"attributes": [
{
"key": { "name": "İşlemci Tipi", "id": 168 },
"value": { "name": "Apple M1", "id": 243383 },
"starred": true,
"description": "",
"mediaUrls": []
},
{
"key": { "name": "SSD Kapasitesi", "id": 249 },
"value": { "name": "256 GB", "id": 3376 },
"starred": true,
"description": "",
"mediaUrls": []
},
.
.
.
]
}
}
Expected Output is getting value by key id: (type must be str)
input >> id: 168
output >> name: Apple M1
Since you originally didn't want a for loop, but now it's a matter of speed,
Here's a solution with for loop, you can test it and see if it's faster than the one you already had
import json
with open("file.json") as f:
data = json.load(f)
search_key = int(input("Enter id: "))
for i in range(0, len(data['product']['attributes'])):
if search_key == data['product']['attributes'][i]['key']['id']:
print(data['product']['attributes'][i]['value']['name'])
Input >> Enter id: 168
Output >> Apple M1
I found the solution with for loop. It works fast so I preferred it.
for i in json_data1['product']['attributes']:
cpu = list(list(i.values())[0].values())[1]
if cpu == 168:
print(list(list(i.values())[1].values())[0])
Iteration is unavoidable if the index is unknown, but the cost can be reduced substantially by using a generator expression and Python's built-in next function:
next((x["value"]["name"] for x in data["product"]["attributes"] if x["key"]["id"] == 168), None)
To verify that a generator expression is in fact faster than a for loop, here is a comparison of the running time of xFranko's solution and the above:
import time
def time_func(func):
def timer(*args):
time1 = time.perf_counter()
func(*args)
time2 = time.perf_counter()
return (time2 - time1) * 1000
return timer
number_of_attributes = 100000
data = {
"product": {
"attributes": [
{
"key": { "name": "İşlemci Tipi", "id": i },
"value": { "name": "name" + str(i), "id": 243383 },
"starred": True,
"description": "",
"mediaUrls": []
} for i in range(number_of_attributes)
]
}
}
def getName_generator(id):
return next((x["value"]["name"] for x in data["product"]["attributes"] if x["key"]["id"] == id), None)
def getName_for_loop(id):
return_value = None
for i in range(0, len(data['product']['attributes'])):
if id == data['product']['attributes'][i]['key']['id']:
return_value = data['product']['attributes'][i]['value']['name']
return return_value
print("Generator:", time_func(getName_generator)(0))
print("For loop:", time_func(getName_for_loop)(0))
print()
print("Generator:", time_func(getName_generator)(number_of_attributes - 1))
print("For loop:", time_func(getName_for_loop)(number_of_attributes - 1))
My results:
Generator: 0.0075999999999964984
For loop: 43.73920000000003
Generator: 23.633300000000023
For loop: 49.839699999999986
Conclusion:
For large data sets, a generator expression is indeed faster, even if it has to traverse the entire set.
I am learning and having much fun with python, currently I am making a simple discord bot but I am stuck with nested dictionary access problem.
This is my command
#bot.command()
async def burek(ctx, arg):
burek_seller = burek_dictionary["bureks"][arg]["seller"]
burek_price = burek_dictionary["bureks"][arg]["price"]
burek_state = burek_dictionary["bureks"][arg]["state"]
burek_name = burek_dictionary["bureks"][arg]["name"]
await ctx.send(
f"{burek_name} is available {burek_state} at {burek_seller} for {burek_price}$."
)
The problem is I want to change 'arg' to search by 'name' in my nested dictionary not by a number of nested dictionary. I am aware I will have to make a few changes, but I have been stuck trying to figure it out for two days now :(
this is my dictionary
burek_dictionary = {
"bureks": {
"0": {
"name": "mesni",
"ingredient": "govedina",
"seller": "sipac",
"price": 2.2,
"state": "hot",
"demand": "low",
},
"1": {
"name": "sirni",
"ingredient": "sir",
"seller": "merc",
"price": 1.8,
"state": "cold",
"demand": "average",
},
"2": {
"name": "spinacni",
"ingredient": "spinaca",
"seller": "pecjak",
"price": 2,
"state": "fresh",
"demand": "high",
},
"3": {
"name": "ajdov",
"ingredient": "sirspinaca",
"price": 2.1,
"state": "hot",
"demand": "average",
},
}
}
Obviously now as 'arg' I have to write a number to achieve my result, but I would like to use 'name' from dictionary and achieve the same result. I have no idea idea how to approach this. I hope it makes sense! Thank you.
Sure.
Loop through the bureks and when you find the one with the matching name, use that.
I assume you might need the same functionality somewhere else, so I broke it out into a separate function.
def find_burek_by_name(name):
for burek_key, burek_info in burek_dictionary["bureks"].items():
if burek_info["name"] == name:
return burek_info
return None # Not found
#bot.command()
async def burek(ctx, arg):
burek_info = find_burek_by_name(arg)
if burek_info:
burek_seller = burek_info["seller"]
burek_price = burek_info["price"]
burek_state = burek_info["state"]
burek_name = burek_info["name"]
await ctx.send(
f"{burek_name} is available {burek_state} at {burek_seller} for {burek_price}$."
)
else:
pass # No such burek
If you know the entire dictionary beforehand, you can build a map from names to numbers, if the dict does not change you build the map in a single pass and avoid looping later:
name2num = {}
for num in burek_dictionary["bureks"]:
name2num[burek_dictionary["bureks"][num]["name"]] = num
print(name2num)
name = "sirni"
num = name2num[name]
burek_seller = burek_dictionary["bureks"][num]["seller"]
burek_price = burek_dictionary["bureks"][num]["price"]
burek_state = burek_dictionary["bureks"][num]["state"]
burek_name = burek_dictionary["bureks"][num]["name"]
print(burek_seller, burek_price, burek_state, burek_name)
Cheers!
Is there any way to pull the key from JSON if the only thing I know is the value? (In groovy or python)
An example:
I know the "_number" value and I need a key.
So let's say, known _number is 2 and as an output, I should get dsf34f43f34f34f
{
"id": "8e37ecadf4908f79d58080e6ddbc",
"project": "some_project",
"branch": "master",
"current_revision": "3rtgfgdfg2fdsf",
"revisions": {
"43g5g534534rf34f43f": {
"_number": 3,
"created": "2019-04-16 09:03:07.459000000",
"uploader": {
"_account_id": 4
},
"description": "Rebase"
},
"dsf34f43f34f34f": {
"_number": 2,
"created": "2019-04-02 10:54:14.682000000",
"uploader": {
"_account_id": 2
},
"description": "Rebase"
}
}
}
With Groovy:
def json = new groovy.json.JsonSlurper().parse("x.json" as File)
println(json.revisions.findResult{ it.value._number==2 ? it.key : null })
// => dsf34f43f34f34f
Python 3: (assuming that data is saved in data.json):
import json
with open('data.json') as f:
json_data = json.load(f)
for rev, revdata in json_data['revisions'].items():
if revdata['_number'] == 2:
print(rev)
Prints all revs where _number equals 2.
using dict-comprehension:
print({k for k,v in d['revisions'].items() if v.get('_number') == 2})
OUTPUT:
{'dsf34f43f34f34f'}
I have a complex json file it included nested dics in it.
it looks like this
{
"objectivelist": [{
"measureid": "1122",
"gradeID": "4222332",
"graduationdate": "May",
"system": {
"platform": "MAC",
"TeacherName": "Mike",
"manager": "Jim",
"studentinfomation": {
"ZIP": "94122",
"city": "SF"
}
},
"measureid": "1122",
"gradeID": "4222332",
"graduationdate": "May",
"system": {
"platform": "MAC",
"TeacherName": "joshe",
"manager": "steven"
},
"studentinfomation": {
"ZIP": "94122",
"city": "SF"
}
}]
}
Here the grade ID and Measured ID are the same, so the result should only need to show one times, and my result should be like this:
{"measureid":"1122","gradeID"4222332","graduationdate":"May"}
I do not need the managername, teachername etc.
not sure how to do this. I try to use comprehensation but do not know who to use it in nest dictionary.
Thank you guys.
Depending on how huge the json file is you may need better solution. We will hash fields which are of interest to us and build the unique json iteratively.
check_set = set()
output = []
interesting_fields = ['measureid', 'gradeID', 'graduationdate']
for dat in X['objectivelist']:
m = hashlib.md5()
m.update(dat['measureid'].encode('utf-8'))
m.update(dat['gradeID'].encode('utf-8'))
m.update(dat['graduationdate'].encode('utf-8'))
digest = m.hexdigest()
if digest not in check_set:
output.append({key: dat[key] for key in ['measureid', 'gradeID', 'graduationdate']})
check_set.add(digest)
And you can find your output in output.
I have a json structured like this:
{ "status":"OK", "copyright":"Copyright (c) 2017 Pro Publica Inc. All Rights Reserved.","results":[
{
"member_id": "B001288",
"total_votes": "100",
"offset": "0",
"votes": [
{
"member_id": "B001288",
"chamber": "Senate",
"congress": "115",
"session": "1",
"roll_call": "84",
"bill": {
"number": "H.J.Res.57",
"bill_uri": "https://api.propublica.org/congress/v1/115/bills/hjres57.json",
"title": "Providing for congressional disapproval under chapter 8 of title 5, United States Code, of the rule submitted by the Department of Education relating to accountability and State plans under the Elementary and Secondary Education Act of 1965.",
"latest_action": "Message on Senate action sent to the House."
},
"description": "A joint resolution providing for congressional disapproval under chapter 8 of title 5, United States Code, of the rule submitted by the Department of Education relating to accountability and State ...",
"question": "On the Joint Resolution",
"date": "2017-03-09",
"time": "12:02:00",
"position": "No"
},
Sometimes the "bill" parameter is there, sometimes it is blank, like:
{
"member_id": "B001288",
"chamber": "Senate",
"congress": "115",
"session": "1",
"roll_call": "79",
"bill": {
},
"description": "James Richard Perry, of Texas, to be Secretary of Energy",
"question": "On the Nomination",
"date": "2017-03-02",
"time": "13:46:00",
"position": "No"
},
I want to access and store the "bill_uri" in a list, so I can access it later on. I've already performed .json() through the requests package to process it into python. print votes_json["results"][0]["votes"][0]["bill"]["bill_uri"] etc. works just fine, but when I do:
bill_urls_2 = []
for n in range(0, len(votes_json["results"][0]["votes"])):
if votes_json["results"][0]["votes"][n]["bill"]["bill_uri"] in votes_json["results"][0]["votes"][n]:
bill_urls_2.append(votes_json["results"][0]["votes"][n])["bill"]["bill_uri"]
print bill_urls_2
I get the error KeyError: 'bill_uri'. I think I have a problem with the structure of the if statement, specifically what key I'm looking for in the dictionary. Could someone provide an explanation/link to explanation about how to use in to find keys? Or pinpoint the error in how I'm using it?
Update: Aha! I got this to work:
bill_urls_2 = []
for n in range(0, len(votes_json["results"][0]["votes"])):
if "bill" in votes_json["results"][0]["votes"][n]:
if "bill_uri" in votes_json["results"][0]["votes"][n]["bill"]:
bill_urls_2.append(votes_json["results"][0]["votes"][n]["bill"]["bill_uri"])
print bill_urls_2
Thank you to everyone who gave me advice.
The error here is cause by the fact that you are looking for a key in the dictionary by called that key itself. Here's a small example:
my_dict = {'A': 1, 'B':2, 'C':3}
Now C may or may not exist in the dict every time. This is how I can check if C exists in the dict:
if 'C' in my_dict:
print(True)
What you are doing is:
if my_dict['C'] in my_dict:
print(True)
If C doesn't exist to begin with my_dict['C'] isn't found and gives you an error.
What you need to do is:
bill_urls_2 = []
for n in range(0, len(votes_json["results"][0]["votes"])):
if "bill_uri" in votes_json["results"][0]["votes"][n]:
bill_urls_2.append(votes_json["results"][0]["votes"][n]["bill"]["bill_uri"])
print bill_urls_2