How to store dictionary entries in a loop? - python

I've been trying to get a dictionary with tuple of strings a key of an integer out of a CSV file but am having trouble.
This is the code I have tried:
fullcsv = [['Brand', 'Swap', 'Candy1', 'Candy2', 'Capacity'],
['Willywonker', 'Yes', 'bubblegum', 'mints', '7'],
['Mars-CO', 'Yes', 'chocolate', 'bubblegum', '1'],
['Nestle', 'Yes', 'bears', 'bubblegum', '2'],
['Uncle Jims', 'Yes', 'chocolate', 'bears', '5']]
def findE(fullcsv):
i = 0
a = {}
while i < len(fullcsv)-1:
i = i + 1
a[i] = ({(fullcsv[i][2],fullcsv[i][3]): int(fullcsv[i][4])})
return a
This is the output for this chunk of code:
{1: {('bubblegum', 'mints'): 7},
2: {('chocolate', 'bubblegum'): 1},
3: {('bears', 'bubblegum'): 2},
4: {('chocolate', 'bears'): 5}}
But the output I'm looking for is more like this:
{('bubblegum', 'mints'): 7,
('chocolate', 'bubblegum'): 1,
('bears', 'bubblegum'): 2,
('chocolate', 'bears'): 5}
so that the tuples aren't numbered and also aren't in their own {}, but just in parentheses ().

Here is a slightly different way if you want.
def findE(fullcsv):
new_dict = {}
for entry in fullcsv[1:]:
new_dict[(entry[2],entry[3])] = entry[-1]
return new_dict

within the function you need to set the key value pair of the dictionary like so
a[(fullcsv[i][2],fullcsv[i][3])] = int(fullcsv[i][4])
so that the full function is
def findE(fullcsv):
i = 0
a ={}
while i < len(fullcsv)-1:
i = i + 1
a[(fullcsv[i][2],fullcsv[i][3])] = int(fullcsv[i][4])
return a
the general syntax is
dictionary[new_key] = new_value

Related

Changing key name of a dictionary by comparing while keeping key value python

I have a dict with two strings "Candy-one" and "Candy-two" as the key and Capacity as the key pair. I wish to replace the strings "Candy-one" and "Candy-two" with the Brand-Name which has the same candies in the same spots "Candy-one" and "Candy-two"
This is what I tried
p = [['Brand-Name', 'Swap', ' Candy-one ', ' Candy-two ', 'Capacity'],
['Willywonker', 'Yes', 'bubblegum', 'mints', '7'],
['Mars-CO', 'Yes', 'chocolate', 'bubblegum', '1'],
['Nestle', 'Yes', 'bears', 'bubblegum', '2'],
['Uncle Jims', 'Yes', 'chocolate', 'bears', '5']]
f = {('bubblegum', 'mints'): 4,
('chocolate', 'bubblegum'): 1,
('bears', 'bubblegum'): 2,
('chocolate', 'bears'): 2}
def Brand(f,p):
i = 0
while i < len(p)-1:
i = i + 1
for key in f:
print(key[0])
print(key[1])
if key[0] == p[i][2] and key[1] == p[i][3]:
f[p[i][0]] = key.pop(key)
return f
print(brand(f,p))
this is my output
{('bubblegum', 'mints'): 4,
('chocolate', 'bubblegum'): 1,
('bears', 'bubblegum'): 2,
('chocolate', 'bears'): 2}
Its as if nothing is happening
This is the output I want
{'Willywonker': 4,
'Mars-CO': 1,
'Nestle': 2,
'Uncle Jims': 2}
Using a double loop is not efficient (quadratic complexity).
Here is how I would solve it:
def Brand(f,p):
# create a mapping dictionary
d = {tuple(x[2:4]): x[0] for x in p[1:]}
# output a new dictionary with replaced keys
# or old key if a new one is not found
return {d.get(k, k): v for k,v in f.items()}
# or if you want to drop in case of no match
# return {d[k]: v for k,v in f.items() if k in d}
Brand(f,p)
output:
{'Willywonker': 4,
'Mars-CO': 1,
'Nestle': 2,
'Uncle Jims': 2}
def Brand(f,p):
res={}
i = 0
while i < len(p)-1:
for key in f:
if key[0] == p[i+1][2] and key[1] == p[i+1][3]:
res[p[i+1][0]] = f[key]
i += 1
return res
new_dict = Brand(f,p)
print(new_dict)
{'Willywonker': 4, 'Mars-CO': 1, 'Nestle': 2, 'Uncle Jims': 2}
Or your corrected attempt:
def Brand(f,p):
res=f.copy()
i = 0
while i < len(p)-1:
for key in f:
if key[0] == p[i+1][2] and key[1] == p[i+1][3]:
res[p[i+1][0]] = res.pop(key)
i += 1
return res
updated_dict = Brand(f,p)
print(updated_dict)
{'Willywonker': 4, 'Mars-CO': 1, 'Nestle': 2, 'Uncle Jims': 2}
key, being a tuple, does not have a pop method, suggesting you never actually try to change f (maybe because you never call Brand).
Plus the stuff #quamrana indicated.

Sort a python dictionary based on input value?

I have a dictionary with four keys a,b,c,d with values 100,200,300,400
list1 = {'a':'100','b':'200','c':'300','d':'400'}
And a variable inputs.
inputs = 'c'
If inputs is c. The list1 dictionary has to be sorted based on it.
inputs = 'c'
list1 = {'c':'300','a':'100','b':'200','d':'400'}
inputs = 'b'
list1 = {'b':'200','a':'100','c':'300','d':'400'}
In Python3.7+ dict keys are stored in the insertion order
k ='c'
d={k:list1[k]}
for key in list1:
if key!=k:
d[key]=list1[key]
Output
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}
Seems like you just want to rearrange your dict to have the chosen value at the front, then the remaining keys afterwards:
dict1 = {'a':'100','b':'200','c':'300','d':'400'}
key = 'c'
result = {key: dict1[key], **{k: v for k, v in dict1.items() if k != key}}
print(result)
# {'c': '300', 'a': '100', 'b': '200', 'd': '400'}
The ** simply merges the leftover filtered keys with key: dict1[key].
If you just want to change the position to the first one a given value if it exists, it could be done in the following way:
list1 = {'a':'100','b':'200','c':'300','d':'400'}
inputs = 'c'
output = {}
if inputs in list1.keys():
output[inputs] = list1.get(inputs)
for i in list1.keys():
output[i] = list1[i]
Output;
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}
Here's a one-liner:
d = {'a':'100','b':'200','c':'300','d':'400'}
i = input()
d = {i:d[i],**{k:d[k] for k in d if k!=i}}
print(list1)
Input:
c
Output:
{'a': '100', 'b': '200', 'd': '400', 'c': '300'}

Saving a Dictionary to a List Without the Dictionary Losing its Value

itemsInExistence = []
item = {}
item['name'] = input("What do you want the new item to be called? ")
item['stats'] = int(input("What is its stat? "))
item['rank'] = int(input("What is its base rank? "))
item['amount'] = int(input("How many of it are there? "))
for i in range(item['amount']):
itemsInExistence.append(item)
later in the code...
gains = random.randint(1, 5)
if gains == 2:
x = -1
for i in itemsInExistence:
x += 1
print(x)
gained_weapon = random.randint(0, x)
print(gained_weapon)
print("You gained the item", itemsInExistence[gained_weapon])
itemMatrix.append(itemsInExistence[gained_weapon])
print(itemMatrix)
for i, item in enumerate(itemsInExistence):
if gained_weapon == itemsInExistence[i]:
del itemsInExistence[i]
break
When item is appended to itemMatrix, it becomes one string. This is a problem, because I need to change the values of item['rank'], item['stats'], and item['amount'] after those values become obsolete. And getting the values by itemMatrix[num][-num] doesn't work, it won't let me change it from a string to an integer.
I'm not entirely sure what you mean by item becomes one string. The code you have posted will result in itemsInExistence being a list containing a number of dictionaries equal to the value item['amount'].
For example:
[
{'name': 'Ball', 'stats': 1, 'rank': 1, 'amount': 2},
{'name': 'Ball', 'stats': 1, 'rank': 1, 'amount': 2}
]
Accessing items inside of this list would be done by itemsInExistence[0]['rank'], changing the integer and string accordingly to access the desired data.
itemsInExistence[1]['rank'] = 4
would then give you as list like this.
[
{'name': 'Ball', 'stats': 1, 'rank': 4, 'amount': 2},
{'name': 'Ball', 'stats': 1, 'rank': 4, 'amount': 2}
]
Update
To access the data inside itemMatrix it would be the same as above with
itemMatrix[-1]['rank'] = 10
# -1 accesses the last item in the list
So if you had something like this
if gains == 2:
x = len(itemsInExistence) -1
gained_weapon = random.randint(0, x)
print("You gained the item", itemsInExistence[gained_weapon])
itemMatrix.append(itemsInExistence[gained_weapon])
print(itemMatrix)
itemMatrix[-1]['rank'] = 10
print(itemMatrix)
You would get the following
What do you want the new item to be called? a
What is its stat? 1
What is its base rank? 2
How many of it are there? 3
You gained the item {'name': 'a', 'stats': 1, 'rank': 2, 'amount': 3}
[{'name': 'a', 'stats': 1, 'rank': 2, 'amount': 3}]
[{'name': 'a', 'stats': 1, 'rank': 10, 'amount': 3}]

How to use a dict comprehension to split a list?

I currently have a dict in the form:
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}]}
I would like the output to be:
op = {"var1":"600103","var2[0]":{"a":"1","b":"2"}}
I am currently using loops to manually loop through. I'd like to know if there's a more pythonic way of doing this.
If this isn't what you're already doing, you can eliminate the need for a nested loop by using a dict comprehension for the values which are lists.
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}, {"a":"22","b":"555"}]}
op = {}
for k in data:
if not isinstance(data[k], list):
op[k] = data[k]
else:
op.update({k + '[{}]'.format(i) : data[k][i] for i in range(len(data[k])) })
And, your output will look like this:
{'var1': '600103', 'var2[1]': {'a': '22', 'b': '555'}, 'var2[0]': {'a': '1', 'b': '2'}}
I do not know if it is very pythonic or not but I know for sure that it is difficult to read :S
Sorry, just playing... ;)
data = {"var1":"600103", "var2":[{"a":"1","b":"2"},{"a":"3","b":"4"},{"a":"5","b":"6"},{"a":"7","b":"8"}], "var3":"600103"}
reduce(
lambda a, b: dict(a.items() + b.items()),
[
dict(map(lambda (idx, i): ('{0}[{1}]'.format(key, idx), i), enumerate(value))) if type(value) is list else {key: value}
for key, value
in data.items()
]
)
output:
{'var1': '600103',
'var2[0]': {'a': '1', 'b': '2'},
'var2[1]': {'a': '3', 'b': '4'},
'var2[2]': {'a': '5', 'b': '6'},
'var2[3]': {'a': '7', 'b': '8'},
'var3': '600103'}

Unable to match tuples items to list items

I have a list (tags) of integers. I want to map the list items to the value items of a dictionary (classes) and get the corresponding dictionary keys as output.
I am using:
h = classes.items()
for x in tags:
for e in h:
# print x, e, # uncomment this line to make a diagnosis
if x == e[1]:
print e[0]
else:
print "No Match"
Classes is the dictionary.
Tags is the list with items that I want to map with the classes. When I run this code, I am getting 2616 time No Match at the output.
2616 = 8 (no. of tuples)*327 (no. of items of tags list)
If I understand what you are trying to do maybe this will help
>>> tags
['0', '2', '1', '3', '4', '7', '2', '0', '1', '6', '3', '2', '8', '4', '1', '2', '0', '7', '5', '4', '1']
>>> classes
{'Tesla': 7, 'Nissan': 0, 'Honda': 5, 'Toyota': 6, 'Ford': 1, 'Mazda': 4, 'Ferrari': 2, 'Suzuki': 3}
tags is a list of strings, not integers - so let's convert it to a list of ints.
>>> tags = map(int, tags)
classes is a dictionary mapping car makes to ints, but we want to use the value as the lookup. We can invert the dictionary (swap keys and values)
>>> classes_inverse = {v: k for k, v in classes.items()}
Now this is what tags and classes_inverse look like
>>> tags
[0, 2, 1, 3, 4, 7, 2, 0, 1, 6, 3, 2, 8, 4, 1, 2, 0, 7, 5, 4, 1]
>>> classes_inverse
{0: 'Nissan', 1: 'Ford', 2: 'Ferrari', 3: 'Suzuki', 4: 'Mazda', 5: 'Honda', 6: 'Toyota', 7: 'Tesla'}
Now we can collect the values of the inverse dictionary for each item in the list.
>>> [classes_inverse.get(t, "No Match") for t in tags]
['Nissan', 'Ferrari', 'Ford', 'Suzuki', 'Mazda', 'Tesla', 'Ferrari', 'Nissan', 'Ford', 'Toyota', 'Suzuki', 'Ferrari', 'No Match', 'Mazda', 'Ford', 'Ferrari', 'Nissan', 'Tesla', 'Honda', 'Mazda', 'Ford']
For each tag, you iterate through all the keys, and print whether it was a match or not, when you except to have at most one hit. For example, if you have 10 items, for each tag, you'll print 1 hit and 9 misses.
Since you want to store this data, the easiest way is to invert the dictionary map, i.e. make key -> value to value -> key. However, this assumes that all values are unique, which your example implies so.
def map_tags(tags, classes):
tag_map = {value: key for key, value in classes.items()}
return [tag_map.get(t, 'No match') for t in tags]
However, be careful. In your classes examples the values are integers, while the tags are strings. You want the two to match when making a map out of them. If the tags are intended to be strings, then change
tag_map.get(t, 'No match')
to
tag_map.get(int(t), 'No match')

Categories