How to select the nearby key in python dictionary? - python

Please consider the below Python code:
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
for k in dict2:
usr_id = 3
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
In the "dict2", if values == 1 then it is active or if values == 0 then it is inactive. Here, match the usr_id with key id in dict2.
Case 1: dict2 = {'1': 1, '2': 1, '3': 1, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==1. so allotted id=3.
Case 2: dict2 = {'1': 1, '2': 1, '3': 0, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==0 . Then next active id is allotted.So allotted id=4.
Case 3: dict2 = {'1': 1, '2': 1, '3': 0, '4': 0, '5': 1}. Now usr_id==3 and dict2 key '3' & '4'==0 . So the next nearest active id to the usr_id want allocate (is nothing but key id '2').How to do it?
Guide me for my case 3 scenario. Thanks in advance.

Assuming you want no efficiency changes to the code, you're overwriting the usr_id in the for k in dict2 loop.
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
usr_id = 3 # Move this out of the loop
for k in dict2:
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
You can write this code to do more checks and utilise the dictionary structure a bit more...
def allot():
# Variables to Enter
dict2 = {1: 1, 2: 1, 3: 0, 4: 0, 5: 1}
usr_id = 3
# Boolean Variables
allotted_id = None
upper_exhausted = False
lower_exhausted = False
# Need to calculate the min and max to know when to stop searching
max_id = max(dict2.keys())
min_id = min(dict2.keys())
# Check the initial ID
if dict2[usr_id] == 0:
print("ID {} inactive. Continuing search.".format(usr_id))
else:
allotted_id = usr_id
# Run two searches - one increasing through the dictionary
# and one decreasing through the dictionary
upper_usr_id = usr_id + 1
lower_usr_id = usr_id - 1
# Run loop whilst the max and min dict key haven't been reached
# AND there's no allotted ID.
while not allotted_id:
if not upper_exhausted:
if dict2[upper_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(upper_usr_id))
if upper_usr_id < max_id:
upper_usr_id += 1
else:
upper_exhausted = True # Maximum has been reached
else:
allotted_id = upper_usr_id
if not lower_exhausted:
if dict2[lower_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(lower_usr_id))
if lower_usr_id > min_id:
lower_usr_id -= 1
else:
lower_exhausted = True # Minimum has been reached
else:
allotted_id = lower_usr_id
# Exhausted all values - No Data value
if upper_exhausted and lower_exhausted:
allotted_id = -999
if allotted_id == -999:
print("Couldn't allot an ID")
else:
print("Allotted ID is: {}".format(allotted_id))
allot()

I would use numpy:
user_ids = np.array(range(5))
valid_user = np.array([1, 1, 0, 0, 1])
anchor_id = 2
dist_from_anchor = np.abs(user_ids - anchor_id)
dist_from_anchor[valid_user == 0] = len(user_ids) +1 #will not be the min
print(np.argmin(dist_from_anchor))
I used the minimum user_id as 0 (just a cs thing...) but you can easily change it to be 1...

I suggest a different approach (Dont know how flexible you are with your approach)-
Store your data like this
dict2 = {"1": {1, 2, 5}, "0": {3, 4}} # 1 for available Ids and 0 for allocated
Now for any incoming user id
if usr_id in dict2["1"]:
allotted_id = usr_id
elif usr_id in dict2["0"]:
# either return the first available Or
# traverse and return the next higher user id available
else:
# exception

Related

Python: JSON, Problem with list of dictionaries, certain value into my dictionary

So, I have been thinking of this for a long time now, but can't seem to get it right. So I have to use a JSON file to make a dictionary where I get the keys: 'userIds' and the value 'completed' tasks in a dictionary. The best I got was the answer: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 90}, with this code under:
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
for user in data1:
if user['completed'] == True:
dict1[key] += 1
print(dict1)
but I feel like this next code would be closer, but I can't figure out how to get it to work
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
for key, value in data1.items():
if user['completed'] == True:
dict1[key].update += 1
print(dict1)
After this, the output is just
" line 24, in
for key, value in data1.items():
AttributeError: 'list' object has no attribute 'items'",
And I do get why, I don't jsut know how to continue from here.
Would really appreciate anyones help, with this obnoxious task.
can u try this ?
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
print(data1)
for x in data1:
for key, value in x.items():
if key =="completed" :
if value == True:
dict1[x["userId"]] += 1
print(dict1)
Try with this approach:
import json
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
for user in data1:
uid = user['userId']
if user['completed']:
dict1[uid] = dict1.get(uid, 0) + 1
elif uid not in dict1:
dict1[uid] = 0
print(dict1)
print(json.dumps(dict1, indent=2))
If needed, you can also simplify the above logic using defaultdict, and leverage the fact that bool is a subclass of int:
from collections import defaultdict
dict1 = defaultdict(int)
for user in data1:
dict1[user['userId']] += user['completed']
Output:
{1: 11, 2: 8, 3: 7, 4: 6, 5: 12, 6: 6, 7: 9, 8: 11, 9: 8, 10: 12}
{
"1": 11,
"2": 8,
"3": 7,
"4": 6,
"5": 12,
"6": 6,
"7": 9,
"8": 11,
"9": 8,
"10": 12
}

I want to create a dict like this from input in python

all the contents must be inserted from the input
graph={
'A':{'B':3,'C':4},
'B':{'A':3,'C':5},
'C':{'B':5,'D':'1'},
'D':{'C':1},
}
Take the input in JSON format and then you can easily use json.loads to convert it to a dictionary.
>>> import json
>>> graph = json.loads(input("Enter graph as JSON: "))
Enter graph as JSON: {"A":{"B":3,"C":4},"B":{"A":3,"C":5},"C":{"B":5,"D":"1"},"D":{"C":1}}
>>> import pprint
>>> pprint.pprint(graph)
{'A': {'B': 3, 'C': 4},
'B': {'A': 3, 'C': 5},
'C': {'B': 5, 'D': '1'},
'D': {'C': 1}}
record_to_insert = int(input("num of record to insert :: "))
dic = {}
for i in range(record_to_insert):
print("")
key_name = input("parent key name :: ")
dic[key_name] = {}
print("Enter how many number of key,value pairs you want for key :: ",
key_name)
num_of_child_keyvalues_to_insert = int(input(""))
for k in range(num_of_child_keyvalues_to_insert):
key = input("child key name :: ")
value = input("Value name :: ")
dic[key_name][key] = value
print(dic)
def make_dict():
d = {}
while True:
key = input("Enter the key of dict or stay blank to finish adding key to this level of dict: ")
if key == "": # just stay blank to out from func
break
ch = input(f"Do you wanna to create nested dict for the key{key}? [y / <Press Enter for No>] ")
if ch == "y":
value = make_dict() # use recursion
else:
value = input(f"Enter the value for the key {key}: ")
d[key] = value
return d
print(make_dict())
link to screenshot

How to sort dictionary values from Highest to lowest?

My question would be how I withdraw winner based on highest score?
since u cant sort in dictionaries
i tried this with lists, but then name wouldnt appear, only the score...
a = {'name_a':0}
b = {'name_b':0}
c = {'name_c':0}
d = {'name_d':0}
e = {'name_e':0}
print("Each time someone scores a point, the letter of his name is typed in lowercase. If someone loses a point, the letter of his name is typed in uppercase")
score = input('Enter series of charachters indicating who scored a poitn: ')
for i in score:
if i == 'a':
a['name_a'] += 1
if i == 'A':
a['name_a'] -= 1
if i == 'b':
b['name_b'] += 1
if i == 'B':
b['name_b'] -= 1
if i == 'c':
c['name_c'] += 1
if i == 'C':
c['name_c'] -= 1
if i == 'd':
d['name_d'] += 1
if i == 'D':
d['name_d'] -= 1
if i == 'e':
e['name_e'] += 1
if i == 'E':
e['name_e'] -= 1
print(a,b,c,d,e)
print('Winner is: ', )
This will work:
max((i, name) for d in (a,b,c,d,e) for name, i in d.items())[1]
you probably want to use a single dict, instead of one for each, like such:
scores = {
'a': 0,
'b': 0,
'c': 0,
'd': 0,
'e': 0,
}
And then you can keep track of the highest scoring player as points are calculated:
point_scored = input('Enter series of charachters indicating who scored a point: ')
for i in point_scored:
if not scores.get(i) is None:
scores[i] += 1
elif not scores.get(i.lower()) is None:
scores[i.lower()] -= 1
else:
print(str(i) + ' is not a valid player...')
winner = max(scores, key=scores.get)
print(scores)
print('Winner is ' + winner)
max_key = ""
max_val = 0
for key, value in d.items():
if (value > max_val):
max_val = value
max_key = key
Is this what you mean?
i found the answer
winner = (sorted(d.items(), key = lambda x: int(x[1]), reverse = True))

Change money with python dynamic programming

Here are two programs for change money problem. The first one is only a recursion program that get all combinations and the second one is using dynamic programming. HOWEVER, i get into trouble when I am working on second one. It is supposed to be faster than the first one, but my program runs FOREVER to do it. I am pretty sure that I am using the dynamic programming, but i don't know what's the problem in it?
Notes: Total is the money going to be changed, units is a list with different values and stored is a dictionary to store the value of a step.
First:
def changeMoney(total, units):
if ( total == 0 ):
return [{}]
elif ( total < 0 ):
return []
else:
n = len(units)
ret = []
for i in range(0,n):
sols = changeMoney(total-units[i],units[i:n])
for sol in sols:
if ( units[i] in sol ):
sol[units[i]] += 1
else:
sol[units[i]] = 1
ret.append(sol)
return ret
print(dpChangeMoney(300,[100,50,20,10,5,2,1],{}))
Second:
import copy
def dpChangeMoney(total, units, stored):
key = ".".join(map(str,[total] + units))
if key in stored:
return stored[key]
else:
if ( total == 0 ):
return [{}]
elif ( total < 0 ):
return []
else:
n = len(units)
for i in range(0,n):
sols = copy.deepcopy(dpChangeMoney(total-
units[i],units[i:n], stored))
for sol in sols:
if ( units[i] in sol ):
sol[units[i]] += 1
else:
sol[units[i]] = 1
if key in stored:
if sol not in stored[key]:
stored[key] += [sol]
else:
stored[key] = [sol]
return stored[key]
print(dpChangeMoney(300,[100,50,20,10,5,2,1],{}))
Here's a much faster way to do this:
def dpChangeMoney(total, units, stored, min_ix=0):
if total < 0:
return []
if total == 0:
return [{}]
if min_ix == len(units):
return []
key = (total, min_ix)
if key in stored:
return stored[key]
sol_list = []
u = units[min_ix]
for c in range(total // u + 1):
sols = dpChangeMoney(total - c*u, units, stored, min_ix + 1)
for sol in sols:
if c > 0:
sol2 = sol.copy()
sol2[u] = c
else:
sol2 = sol
sol_list.append(sol2)
stored[key] = sol_list
return sol_list
If invoked as follows, it prints the number of solutions for the specified case:
print(len(dpChangeMoney(300, [100,50,20,10,5,2,1], {})))
The result is:
466800
On my system this took well under a second to run. (Of course, you could print the actual solutions, but there are a lot!)
To see the actual solutions for a total of 10:
print(dpChangeMoney(10, [100,50,20,10,5,2,1], {}))
The result is:
[{1: 10}, {1: 8, 2: 1}, {1: 6, 2: 2}, {1: 4, 2: 3}, {1: 2, 2: 4}, {2: 5}, {1: 5, 5: 1}, {1: 3, 2: 1, 5: 1}, {1: 1, 2: 2, 5: 1}, {5: 2}, {10: 1}]
i just figure out what is the problem in my algorithm. I will update a much faster algorithm after the due date. Thanks for your suggestions and instructions. E

Syntax and lists within lists

I am creating a vote system to pick a team, butI have hit a wall. The code works fine up until the point of decision2. Any ideas?
Please remember this code is a work-in-progress.
teamNames = []
teams = {}
easy = [0, 1, 2, 3, 4, 5]
NoVotes1 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes2 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes3 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes4 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes5 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
while True:
print("Enter team name " + str(len(teamNames) + 1) + (" or press enter to stop."))
name = input()
if name == "":
break
teamNames = teamNames + [name]
print("The team names are ")
for name in teamNames:
print(" " + name)
for name in teamNames:
teams[name] = 0
teamNames.sort()
print("In alphabetical order the team names are ")
print()
print(str(teamNames))
y = 0
decision1 = input("Would you like to enter a vote? (1 = yes, 2 = no)")
while decision1 == "1":
print("ok great, where did " + teamNames[y] + " come")
decision2 = input()
if decision2 == "1":
teams[easy[y]] = teams[easy[y]] + 1
y = y + 1
if decision1 == "2":
break
elif n == "6":
break
I think I see what you've misunderstood. Standard dictionaries, unlike lists, have no concept of order or the nth (e.g. first) item. They are just associations between keys and values. When you say teams[key] = value you are setting the value at key, when you say value = teams[key] you are getting the value at key. It's possible that key is a number but it doesn't have to be, and if key is 1 then that doesn't mean the second value in the dictionary, or the first, or any other position. Perhaps this example interactive session will help you understand:
>>> dictionary = {"a": "b", "c": "d"}
>>> dictionary = {"a": "b", "c": "d", 5: "e"}
>>> dictionary[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1
>>> dictionary["c"]
'd'
>>> dictionary[5]
'e'
What you want is teams[teamNames[y]] = teams[teamNames[y]] + 1, which by the way can be shortened to teams[teamNames[y]] += 1.
Does all that make sense? If not I suggest doing some simple experiments with dictionaries until you understand them better. Play around with the in the shell. Write some small programs using dictionaries to see what they do.

Categories

Resources