Python dictionary get method in assignment [duplicate] - python

This question already has an answer here:
Dictionary syntax error "can't assign to function call"
(1 answer)
Closed 9 months ago.
All,
I'm looping over a dictionary and counting the values that occur. To do this, I'm using the get method in the assignment statement for another dictionary. This returns a syntax error "can't assign to function call"
counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key,value in mydict.iteritems():
counts(value[1]) = counts.get(value[1], 0) + 1
Why would the assignment try to point to the function, rather than the return value?

counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key,value in mydict.iteritems():
counts[value[1]] = counts.get(value[1], 0) + 1
You need brackets, not parenthesis, to get an item from a dictionary.
Also, You're doing this the hard way.
from collections import defaultdict
# automatically start each count at zero
counts = defaultdict(int)
# we only need the values, not the keys
for value in mydict.itervalues():
# add one to the count for this item
counts[value[1]] += 1
or
# only on Python 2.7 or newer
from collections import Counter
counts = Counter(value[1] for value in mydict.itervalues())

Instead of counts(value[1]) = ... you want counts[value[1]] = ....

Change this:
counts(value[1])
to this:
counts[value[1]]
Code looks like this:
counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key, value in mydict.iteritems():
counts[value[1]] = counts.get(value[1], 0) + 1

counts[value[1]] = counts.get(value[1], 0) + 1
should be
counts[value[1]] = counts.get(value[1], 0) + 1

Related

Function to check if dictionary value is occupied

I'm trying to make a function to check whether a value added to a dictionary already exists.
If a value is already in the dictionary, it should print "Occupied" and not add the value to the existing key.
I have tried to get it to not append when the new input is similar, but it still adds the new input even though it is the same as the previous.
For example, if I add input_v as "Hi" --> XO = {'key': ["Hi"]}
If I were to put in "Hi" again, I then want it to say "Occupied", but as of right now it still adds to the dictionary.
XO = {'key': []}
def check_values(input_v):
value = input_v
print(XO)
if value in XO.values():
print("Occupied")
else:
XO['key'].append(value)
The issue is in the way you referenced the value of the 'key'. Use this:
XO = {'key': []}
def check_values(input_v):
value = input_v
global XO
#print(XO)
if value in XO['key']:
print("Occupied")
else:
XO['key'].append(value)
#print(XO)
d = dict()
for c in a:
if c not in d:
d[c] = 1
else:
print("Occupied")
Would this work? a is a list in this example.

Recursively create a nested dictionary from string [duplicate]

This question already has answers here:
Converting list to nested dictionary
(4 answers)
Closed 5 years ago.
I have an issue that I've been trying to sort out. I have a string that needs to be converted to an nested dictionary with the keys and values based off the adjacent words in the string. Here is an example:
graphMaster = {}
inputSentence = "I have a dog named Max."
I would like to take this string, and convert it into a dictionary resembling the output below:
print graphMaster
{'I': {'have': {'a': {'dog': {'named': 'Max'}}}}}
I have tried the following:
graphMaster = {}
inputSentence = "I have a dog named Max."
while True:
inputList = inputSentence.strip().split(' ')
for currentIndex, word in enumerate(inputList):
nextIndex = currentIndex + 1
if nextIndex < len(inputList):
if word not in graphMaster.keys():
graphMaster[word] = inputList[nextIndex]
elif word in graphMaster.keys():
break
print graphMaster
I couldn't find a duplicate problem here and I pre-apologize if one exists that I couldn't find. Any help is greatly appreciated.
You could do something like this:
outdict = {}
curdict = outdict
for f in inputSentence.split(' '):
curdict[f] = {}
curdict = curdict[f]
print outdict
Where curdict is only pointing to a location in the output dictionary.

prevent OrderedDict from splitting single string value into characters during iteration

I would like to make an OrderedDict with a string for each key and a list of strings for each value.
from collections import OrderedDict
# Compare a dict with an OrderedDict
someDict = dict(a = ["foo","bar"], b = ["baz"])
someOrderedDict = OrderedDict([("a",("foo","bar")),("b",("baz"))])
I need to iterate over this dictionary with access to both the key and the values. On a vanilla dictionary, this is simply:
for k,v in someDict.items():
for eachv in v:
print("do something with key = " + k + " and value = " + eachv)
# returns the desired output:
# do something with key = a and value = foo
# do something with key = a and value = bar
# do something with key = b and value = baz
(If this can be done in a comprehension, please enlighten me -- I couldn't figure out how to do without losing access to the key.)
When I try this on the OrderedDict I get:
for k,v in someOrderedDict.items():
for eachv in v:
print("do something with key = " + k + " and value = " + eachv)
# results in undesirable splitting of value "baz" into ["b","a","z"]:
# do something with key = a and value = foo
# do something with key = a and value = bar
# do something with key = b and value = b
# do something with key = b and value = a
# do something with key = b and value = z
What am I doing wrong?
This is because you're assigning a string (("baz")) to the b key, rather than a tuple (("baz",)) or list of strings.
Instead of
someOrderedDict = OrderedDict([("a",("foo","bar")),("b",("baz"))])
try
someOrderedDict = OrderedDict([("a",("foo","bar")),("b",("baz",))])
(Note the new comma.)
You can add a , after "baz" so it can get interpreted as a tuple instead of a single str during the for loop:
someOrderedDict = OrderedDict([("a",("foo","bar")),("b",("baz",))])
Then, iteration works fine grabbing the single element of the tuple baz:
for k,v in someOrderedDict.items():
for eachv in v:
print("do something with key = " + k + " and value = " + eachv)
do something with key = b and value = baz
do something with key = a and value = foo
do something with key = a and value = bar
The same could be achieved by wrapping the values in []:
[("a", ["foo","bar"]),("b", ["baz"])]
Even better, if you already have the dictionary available, just expand (unpack) the dictionary someDict in someOrderedDict by utilizing the ** syntax:
someOrderedDict = OrderedDict(**someDict)
it works equally well and looks much more compact and clean.

checking if key's already in dictionary with try except

I'm using a dictionary to count how many times different items appear in a dataset. In the init of the class, I create the property as a dictionary like this
self.number_found = {}
The first time I find any particular item, I would get a KeyError if I try to do this because the item isn't in the dictionary yet
self.number_found[item] = 1
so I ended up creating a function that checks if an entry is already in the dictionary and if not, adds it for the first time
def _count_occurrences(self, item):
try:
#this checks to see if the item's already in the dict
self.number_found[item] = self.number_found[item] + 1
x = self.number_found[item]
except KeyError:
x = 1
#this adds an item if not in the dict
self.number_found[item] = x
return x
However, this is not working as intended if I find a second occurrence of an item in a dataset.
Let's say there are two 'elephant' in my dataset. When I print self.number_found to the console this is what I get
{'elephant': 1}
{'elephant': None}
and I get this error when adding the second occurrence
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
Question: what's the right way to check if the key's already in the dictionary (with an explanation as to why the 1 is changing to a None)
You can use a defaultdict:
from collections import defaultdict
self.number_found = defaultdict(int)
The first time an item is accessed, its value will take a default of 0
A None is returned because you're not returning anything in your try branch
The return at the end of the except block must be moved out. That way, x is returned for both cases
class C(object):
def __init__(self):
self.number_found = {}
def _count_occurrences(self, item):
try:
#this checks to see if the item's already in the dict
self.number_found[item] = self.number_found[item] + 1
x = self.number_found[item]
except KeyError:
x = 1
#this adds an item if not in the dict
self.number_found[item] = x
return x
c = C()
r = c._count_occurrences('elephant')
print r
print c.number_found
r = c._count_occurrences('elephant')
print r
print c.number_found
Here is a test run first with outdented return, then with it where you have it in your OP:
jcg#jcg:~/code/python/stack_overflow$ python number_found.py
1
{'elephant': 1}
2
{'elephant': 2}
jcg#jcg:~/code/python/stack_overflow$ python number_found.py
1
{'elephant': 1}
None
{'elephant': 2}
As you can see, the second version returns None since there is no return from the _count_occurrences try block

What is the best way to append lists inside a dict?

I am trying to build a list that has 1 key to many values. The best way I can think to do this is by pointing a key value to a list. However, I am having trouble building the lists inside the dict.
num_items = len(decoded_data['data']['arrivalsAndDepartures'])
buses = list()
busdict = dict()
val = list()
for i in range(num_items):
decoded_data['data']['arrivalsAndDepartures']
bus = decoded_data['data']['arrivalsAndDepartures'][i]['routeId']
buses.append(bus)
try:
busdict[bus]
except KeyError:
busdict[bus] = [i]
print("except "+ bus , str(i))
else:
val = busdict[bus]
busdict[bus] = [val].append(i)
print("else "+ bus ,val, str(i))
This gives me weird results.
$ python test.py
except 40_590 0
except 40_554 1
except 40_592 2
else 40_590 [0] 3
except 1_122 4
except 40_577 5
else 40_590 None 6
From the above test result, the third time it hits the key '40_590' the value is cleared.
busdict[bus] = [val].append(i)
list.append is an inplace operation and returns None. So, you are clearing the previously stored list in it. You could fix it like this
busdict[bus].append(i)
But the best way to solve this problem is by using dict.setdefault function (which assigns and returns the default value if the specified key is not found), like this
busdict.setdefault(bus, []).append(i)
But the best way to solve this problem would be to use collections.defaultdict, like this
from collections import defaultdict
busdict = defaultdict(list)
...
...
busdict[bus].append(i)
list.append() does not return a value. Use it like this:
else:
val = busdict[bus].append(i)
print("else "+ bus ,val, str(i))
By the way: use four spaces for indents!

Categories