I want to separate each (key, value) pair from a dictionary and want to call each value by its key name.
I have two lists,
1. ListA = [1, 2, 3, 4, 5]
2. ListB = ['A', 'B', 'C', 'D', 'E']
Now I have created a dictionary like this,
Dict = {1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E'}
So, now if I want to see value for each key, I have to type:
Dict[key].
Now I expect my result to be like:
If I ask for the value of each key, I have to just type key not Dict[key]
and it should give me the answer.
Typing 1 should give A.
Typing 2 should give B.
You can somehow do like this but you if you can simply access below is not a very good idea honestly. You can set key as attribute of an object.
But it wont work for the dictionary you have my Input Dictionary is {"key1":"Apple"}
class MyDict:
def __init__(self,input_dict):
for key,value in input_dict.items():
setattr(self,key,value) #setting key as attribute
obj = MyDict({"key1":"Apple"}) #new instance
print(obj.key1) # this will print Apple
But still it wont work like obj.1 better not to mess it.
If you want to loop over dictionary values, you can use Dict.values():
for v in Dict.values():
print(v)
# > 'A'
# > 'B'
# ...
Inside a while true loop, keep popping items from your lists until you run into an IndexError like this:
ListA = [1, 2, 3]
ListB = ['A', 'B', 'C']
DictC = {}
while True:
try:
DictC[ListA.pop(0)] = ListB.pop(0)
except IndexError:
break
print(DictC)
Related
I am trying to join a list to a dictionary in Python 3 and return the sum of the key values.
So far, I can't join the two, I've tried using get and set and am not succeeding.
I also tried a for loop with set linking listy and dict2, like this:
dict2 = {
1: "A",
2: "B",
3: "C"
}
listy = ['A', 'M', 'B', 'A']
for k in dict2:
if set(listy) & set(dict2[value]):
print(dict2.key)
This is the error I'm getting in IPython:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-291-5a5e2eb8d7f8> in <module>
10
11 for k in dict2:
---> 12 if set(listy) & set(dict2[value]):
13 print(dict2.key)
14
TypeError: unhashable type: 'list'
You can use a list-comprehension:
[x for x in listy if x in set(dict2.values())]
In code:
dict2 = {
1: "A",
2: "B",
3: "C"
}
listy = ['A', 'M', 'B', 'A']
print([x for x in listy if x in set(dict2.values())])
# ['A', 'B', 'A']
Your task will be easier if you flip the keys and values in your dictionary. I assume that there are no duplicate values.
dict2 = {1: "A", 2: "B", 3: "C"}
lookup = {value: key for key, value in dict2.items()}
Now lookup is {'A': 1, 'B': 2, 'C': 3}.
Now you can loop over the list:
listy = ['A', 'M', 'B', 'A']
result = []
for key in listy:
if key in lookup:
result.append(key)
Now result is ['A', 'B', 'A']. The code will be shorter with a list comprehension:
result = [key for key in listy if key in lookup]
As far as I unterstood the question you want to get the sum of the keys in dict2 for every entry in listy that has a corresponding value in dict2. If you have created the lookupdictionary you can do the following to get the single values.
[lookup.get(key, 0) for key in listy]
# -> [1, 0, 2, 1]
If a key doesn't appear in the dictionary it gets a default value of 0.
To get the sum is easy now
sum(lookup.get(key, 0) for key in listy)
# -> 4
You probably meant to use dict[k] instead of dict2[value]
Also your dictionary's entries contain single values (not lists) so you can use the in operator:
for example:
# if listy is a dictionary or a small list, you don't need to build a set
for key,value in dict2.items():
if value in listy:
print(key)
or :
# If listy is a large list, you should build a set only once
listySet = set(listy)
for key,value in dict2.items():
if value in listySet:
print(key)
If you have a lot of code to perform on the "joined" data, you could structure the condition like this:
for key,value in dict2.items():
if value not in listy: continue
print(key)
... do more stuff ...
If you're only looking for a sum, you can do it more directly:
# counting sum of dict2 keys matching each value in listy
# select sum(dict2.key) from listy join dict2 where dict2.value = listy.value
# (note that an inverted dict2 would be better suited for that)
result = sum(key*listy.count(value) for key,value in dict2.items())
# counting sum of keys in dict2 that have a value in listy
# select sum(dict2.key) from dict2 where exists listy.value = dict2.value
result = sum(key for key,value in dict2.items() if value in listy)
In short, you have to implement the linking logic that the RDBMS query optimizer normally does for you in SQL.
I am trying to create a dictionary using two lists without the use of zip. can someone help me to finish the code. The function should return an empty dictionary if the lists were empty.
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0:
for i in range(len(key_list)):
dict[key_list[i]]=value_list[i]
return new_dict
the output I want is
new_dict={1:'a', 2:'b', 3:'c', 4:'d'}
Your return should go outside the for loop scope, also check for the min lenght of both lists:
def list_to_dict(key_list,value_list):
new_dict = {}
if len(key_list) != 0 and len(value_list) != 0:
for i in range(min(len(key_list), len(value_list))):
new_dict[key_list[i]] = value_list[i]
return new_dict
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0 and len(key_list) == len(value_list):
for key, index in enumerate(key_list):
dict[key]=value_list[index]
return new_dict
You had an error in your indentation. Also, both lists need to be the same length to avoid an error, so I added that check. For extra learning, look up enumerate. GL on the rest of your homework :)
Try this.
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0:
for i in range(len(key_list)):
new_dict[key_list[i]]=value_list[i]
return new_dict
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
"""using dict comprehension, creating new key-value pair
for each key present in key list againt the value present in the value list."""
new_dict={key_list[i]:value_list[i] for i in range(len(key_list))}
return new_dict
result = list_to_dict(key_list,value_list)
print(result)
output
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
You can use a dict comprehension:
key_list = [1, 2, 3, 4]
value_list=['a', 'b', 'c', 'd']
def list_to_dict(key_list, value_list):
assert len(key_list) == len(value_list), "Both input lists should have equal length"
return {key_list[i]: value_list[i] for i in range(len(key_list))}
key_list = [1, 2, 3, 4]
value_list=['a', 'b', 'c', 'd']
my_dict={}
def list_dict(key_list,value_list):
for i in range((len(key_list))-1):
my_dict[key_list[i]] = value_list[i] #using loop to add one by one
i=i+1
return my_dict
You can try this for your home work
list_dict(key_list,value_list)
I have got the below problem.
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
Normal retrieval method: dict1['a'] -> Output - > 1
expected method: dict1['a', 'b'] - > Output - > [1, 2]
My requirement is to extract multiple values from a dictionary by providing multiple keys at the same time as mentioned in the expected method above.
Is there a way to do it? If I have to edit the built-in dict class methods, how do I do it?
You can do what's said in the other answers or use map on your list of keys with the get dictionnary method :
map(dict1.get, ["a", "b"])
Use a list comprehension:
[ dict[k] for k in ('a','b')]
[ dict[k] for k in my_iterable ]
will throw KeyError if any of the keys in the iterable are not in the dict. It may be better to do
[ dict.get(k, my_default_value) for k in my_iterable ]
You can use list comprehension : [dict1[key] for key in ('a', 'b')]
It is equivalent to
output = []
for key in ('a', 'b'):
output.append(dict1[key])
This is one way of doing this through subclassing:
class CustomDict(dict):
def __init__(self, dic):
self.dic = dic
def __getitem__(self, items):
values = []
for item in items:
values.append(self.dic[item])
return values if len(values) > 1 else values[0]
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
new_d = CustomDict(d)
print(new_d['a'])
print(new_d['a', 'b'])
print(new_d['a', 'b', 'c'])
print(new_d['a', 'c', 'd'])
Output:
1
[1, 2]
[1, 2, 3]
[1, 3, 4]
Explanation:
The new_d is an object of the CustomDict class, it will always fall back to the parent class's methods (so that looping over the object and other things you might want to do to a dictionary work) except when one of the overriden methods (init, getitem) get called.
So when one uses new_d['a', 'b'] the overriden __getitem__ method gets called. The overriden method uses the __getitem__ of the self.dic (which is a normal dictionary) to actually access the dictionary values for every key given.
I am parsing some XML data from Open Street Map into JSON (later to be uploaded into a database). It is large, so I am using iterparse. I have some tags that look like this
<tag 'k'=stringA:stringB:stringC 'v'=value>
which I want to parse into
{stringA: {stringB: {stringC: value} } }
I have done so with an ugly hardcode. However, I would like to create a function that uses recursion to address the same issue in case the 'k' attribute value contains arbitrarily as many ':'.
I created this
def nestify(l):
"""Takes a list l and returns nested dictionaries where each element from
the list is both a key to the inner dictionary and a value to the outer,
except for the last element of the list, one which is only a value.
For best understanding, feed w = [ 'a', 'b', 'c', 'd', 'e', 'f', 'v'] to the
function and look at the output."""
n = len(l)
if n==2:
key = l[0]
value = l[1]
else:
key = l[0]
value = nestify(l[1:])
return {key:value}
which works. (You have to make the keys and value into a list first.) Except not really, because it always makes a new dictionary. I need it to respect the previous data and integrate. For example, if my parser encounters
<tag 'k'=a:b:c 'v'=1 />
and then in the same element
<tag 'k'=a:d:e 'v'=2 />
I need it to make
{a: {'b': {'c' : 1}, 'd' : {'e' : 2}}}
and not
{a: {'b' : {'c' : 1}}}
{a: {'d' : {'e' : 2}}}
I have tried this code:
def smart_nestify(l, record):
n = len(l)
if n==2:
key = l[0]
value = l[1]
else:
key = l[0]
value = smart_nestify(l[1:], key)
if key not in record:
return {key:value}
else:
record[key] = value
return record
but it still writes over and returns only the latest record. Why is that? How can I fix this code?
Here is a "smarter" nestify that merges a list l into the dictionary record:
def smarter_nestify(l, record):
if len(l) == 2:
return {l[0]: l[1]}
key = l.pop(0)
record[key] = smarter_nestify(l, record.get(key, {}))
return record
Each time through the recursion, it pops the first element from the list l.pop(0) and merges the value from the next level of the dictionary record.get(key, {}).
You can call it with two lists like this:
l = ['a', 'b', 'c', 1]
record = smarter_nestify(l, {})
l = ['a', 'd', 'e', 2]
record = smarter_nestify(l, record)
print record
Sometimes it is better to just use iteration rather than recursion. Here’s the iterative answer.
g_values = dict()
def make_nested(l):
"""
l is the array like you have for nestify
e.g., ['a', 'b', 'c', 1 ] or ['a', 'd', 'e', 2]
"""
global g_values
value = l[-1] ; l = l[:-1]
last_dict = None
for x in l[:-1]:
mp_temp = last_dict if last_dict is not None or g_values
last_dict = mp_temp.get(x)
if last_dict is None:
mp_temp[x] = dict()
last_dict = mp_temp[x]
last_dict[l[-1]] = value
While I didn’t test it, you could also try something like this recursively:
def make_nested(values, l):
if len(l == 2):
values[l[0]] = l[1]
return
mp = values.get(l[0])
if mp is None:
values[l[0]] = dict()
make_nested(values[l[0]], l[1:])
else:
make_nested(mp, l[1:])
I have a list of lists as follows
[
['a', 1],
['b',2],
['c',1],
['a', 2],
['c', 5]
]
I want to normalize this list in such a way that for every, 'a', 'b', 'c' etc, I have only one unique entry in the list, and for every duplicate list, the second value which is the quantity is added so that I get something like:
[
['a', 3], # so since 'a' already existed the quantity is added 1 + 2 becomes 3
['b',2],
['c',6] # similarly for 'c' it becomes 1 + 5 = 6
]
How to do this with Python ?
I'd suggest use collections.defaultdict() like below:
from collections import defaultdict
l = [
['a', 1],
['b',2],
['c',1],
['a', 2],
['c', 5]
]
d = defaultdict(int)
for key, value in l:
d[key] += value
print(d.items())
Output:
dict_items([('b', 2), ('a', 3), ('c', 6)])
Also you can use a try...expect instead of collections.defaultdict()...if you'd like:
d = {}
for key, value in l:
try:
d[key] += value
except KeyError:
d[key] = value
Also, you can try if...else:
d = {}
for key, value in l:
if key in d:
d[key] += value
else:
d[key] = value
here is a long way to do it, but returns a list, not a data object
def normalizelist(inp):
out=[]
for key,count in inp:
exist=0
for place, val in enumerate(out):
if (key==val[0]):
out[place][1]+=count
exist=1 #found it, so don't need to make it
break #no need to go further
if (exist==0): #didn't find it, therefor it needs to be added
out.append([key,count])
return out
hopefully that helps!