This question already has answers here:
Return a default value if a dictionary key is not available
(15 answers)
Does Python have a defined or operator like Perl? [duplicate]
(2 answers)
Make value_counts() return 0 if the value does not occur
(1 answer)
Default dict keys to avoid KeyError
(4 answers)
Closed 5 years ago.
I have a situation where some city names need to be renamed, so I am using a dict where the keys are the old city names and the values are the new ones. However, only some cities need to be renamed so not all possible cities are in the dict.
The only way I know how to do it is to except a KeyError when the city doesn't need to be renamed, which works, but I'm not sure if this is bad practice, or if there are any downfalls to this. Is there something I am missing?
# Set Venue
venue_name = unidecode(cell[2].get_text())
try:
# Correct venue names i.e. Cairns, QLD = Cairns
venue_name = VENUE_NAMES_DICT[venue_name]
except KeyError:
pass
As #jarmod suggests, you can use the .get() method of the standard Dictionary to provide a default value in case the key is missing. What isn't described is that this approach enables you to turn your problem into a one-liner by passing the venue_name value to .get() as the default value.
# Set Venue
venue_name = unidecode(cell[2].get_text())
# Correct venue names i.e. Cairns, QLD = Cairns
venue_name = VENUE_NAMES_DICT.get(venue_name, venue_name)
If venue_name is present as a key in the dictionary, .get() will return the desired new value. If it isn't present, .get() will return the original value of venue_name unchanged. This eliminates the need for any conditional logic.
What you can do is use defaultdict
from collections import defaultdict
d=defaultdict(list) #this will return a empty list everytime a new key is used or if key exists it will appendt the value to the list
d[venue_name]=a
Example:
>>> from collections import defaultdict
>>> city_list = [('TX','Austin'), ('TX','Houston'), ('NY','Albany'), ('NY', 'Syracuse'), ('NY', 'Buffalo'), ('NY', 'Rochester'), ('TX', 'Dallas'), ('CA','Sacramento'), ('CA', 'Palo Alto'), ('GA', 'Atlanta')]
>>>
>>> cities_by_state = defaultdict(list)
>>> for state, city in city_list:
... cities_by_state[state].append(city)
...
for state, cities in cities_by_state.iteritems():
... print state, ', '.join(cities)
...
NY Albany, Syracuse, Buffalo, Rochester
CA Sacramento, Palo Alto
GA Atlanta
TX Austin, Houston, Dallas
You can use dict.get(key, default_value) and supply a default value.
You can use "in", like this:
data = ['Chicago', 'NYC', 'Boston', 'SD']
dictionary = {'NYC': 'New York', 'SD': 'San Diego'}
new_list = []
for x in data:
if x in dictionary:
new_list.append(dictionary[x])
else:
new_list.append(x)
print(new_list)
#output
['Chicago', 'New York', 'Boston', 'San Diego']
Using List comprehension
data = ['Chicago', 'NYC', 'Boston', 'SD']
dictionary = {'NYC': 'New York', 'SD': 'San Diego'}
new_list=[dictionary[x] if x in dictionary else x for x in data]
print(new_list)
['Chicago', 'New York', 'Boston', 'San Diego']
In general, throwing exceptions for non-exceptional situations is poor design. You want a defaultdict.
from collections import defaultdict
renames = defaultdict(lambda: None)
# Add the elements to renames here ...
Now, renames is a dictionary, except that if the key doesn't exist, it returns None rather than throwing, so you can just check if the value is None to see if it needs to be renamed.
Related
How do you use Python to accomplish the following:
I have the following list
StateCityList = [["Kansas","Overland Park"],
["Kansas","Lenexa"],
["Kansas","Olathe"],
["Missouri","Kansas City"],
["Missouri","Raytown"],
["Missouri","Independence"],
["Texas","Dallas"],
["Texas","Houston"],
["Texas","San Antonio"]]
I want to get all the cities in a certain state into a separate list like this
Kansas =[["Kansas","Overland Park],
["Kansas","Lenexa"],
["Kansas","Olathe"]]
Missouri = [["Missouri","Kansas City"]
["Missouri","Raytown"]
["Missouri","Independence"]]
Texas = [["Texas","Dallas"]
["Texas","Houston"]
["Texas","San Antonio"]]
Thanks
You can use operator.itemgetter and itertools.groupby:
>>> from itertools import groupby
>>> from operator import itemgetter
>>> {k: list(g) for k, g in groupby(StateCityList, key=itemgetter(0))}
{'Kansas': [['Kansas', 'Overland Park'],
['Kansas', 'Lenexa'],
['Kansas', 'Olathe']],
'Missouri': [['Missouri', 'Kansas City'],
['Missouri', 'Raytown'],
['Missouri', 'Independence']],
'Texas': [['Texas', 'Dallas'],
['Texas', 'Houston'],
['Texas', 'San Antonio']]}
NOTE:
If StateCityList is not sorted by state name, then use this:
{k: list(g) for k,g in groupby(sorted(StateCityList, key=itemgetter(0)), itemgetter(0))}
Using setdefault:
StateCityDict = {}
for state, city in StateCityList:
StateCityDict.setdefault(state, []).append([state, city])
Somewhat more beginner-friendly code. I like the one above though.
StateCityList = [["Kansas","Overland Park"],
["Kansas","Lenexa"],
["Kansas","Olathe"],
["Missouri","Kansas City"],
["Missouri","Raytown"],
["Missouri","Independence"],
["Texas","Dallas"],
["Texas","Houston"],
["Texas","San Antonio"]]
sc = {}
for state, city in StateCityList:
if state in sc:
sc[state].append((state,city))
else:
sc[state] = [(state, city)]
# print
for state in sc:
print(state, sc[state])
solution using set
You don't need to import any packages to perform this task as you can identify the list of unique States using set, :
# find unique set of states using "set"
states=set([k[0] for k in StateCityList])
# build dictionary splitting by city:
res={}
for s in states:
res[s]=[k for k in StateCityList if k[0]==s]
giving the resulting dictionary:
{'Missouri': [['Missouri', 'Kansas City'], ['Missouri', 'Raytown'], ['Missouri', 'Independence']], 'Texas': [['Texas', 'Dallas'], ['Texas', 'Houston'], ['Texas', 'San Antonio']], 'Kansas': [['Kansas', 'Overland Park'], ['Kansas', 'Lenexa'], ['Kansas', 'Olathe']]}
nicer output: Avoid duplication of State information in result
This answers the question as you set it, but do you really need to repeat the State within the resulting list? I think it is neater to leave it out in this way:
res={}
for s in set([k[0] for k in StateCityList]):
res[s]=[c for k,c in StateCityList if k==s]
Which gives a neater dictionary, with the key=State and the entry a list of the cities:
{'Missouri': ['Kansas City', 'Raytown', 'Independence'],
'Texas': ['Dallas', 'Houston', 'San Antonio'],
'Kansas': ['Overland Park', 'Lenexa', 'Olathe']}
alternative using zip
I haven't tested it but suspect it is faster for large datasets if you substitute the first iterator for the zip command, although I prefer the iterator in most circumstances as I find the code clearer and easier to understand:
res={}
for s in set(list(zip(*StateCityList))[0]):
res[s]=[k for k in StateCityList if k[0]==s]
I have some data on a dictionary. Each key in the dictionary has several values, one of them is called 'state' which can be equal to Georgia, Washington, etc. I want to get the unique states. I tried doing this but I get an incorrect syntax error
s = set( value for key in r value = key['state'] )
How can I get all the states?
Edit:
The data structure I have is actually a list of dictionaries so I want to get the values of r[0]['state'], r[1]['state'], etc and make an unique list.
Based on your comment since you have a list of dictionaries you can use map function with passing dict.get method to it, to get all state values then you can loop over the values within a set :
s = set( value for value in map(lambda x:x.get('state'),r))
Or for get ride of lambda function you can use operator.itemgetter :
from operator import itemgetter
s = set( value for value in map(itemgetter('state'),r))
So you have a dictionary, and each key-value pair has another dictionary inside value, where one of the keys for these "inner" dictionary is state?
In that case:
my_dict = {'somekey': {'a':1,'b':2, 'state':'georgia'}, 'otherkey': {'a':1,'b':2, 'state':'washington'}}
[val['state'] for key, val in my_dict.iteritems()]
['georgia', 'washingon']
Just guessing at your data structure, but if it's like this:
r = {'home': {'address': '123 Oak Avenue', 'city': 'My town', 'state': 'State'},
'work': {'address': '456 Main Street', 'city': 'Big city', 'state': 'State'}}
then you can use this to retrieve the states:
s = set(r[key]['state'] for key in r)
I have lists of names and cities and am trying to compile a list of the number of users in each city.
I want to have a list that looks like:
citylist = (['New York', 53], ['San Francisco', 23], ['Los Angeles', 54])
etc.
First problem I have is that when I read a new line from the file I need to check whether that city already exists. If it doesn't then I need to add it and give it the number 1. So I have tried:
if city not in citylist:
citylist.append([city, 1])
Problem with that is that even if the city is already in the list the search doesn't work as I guess it is typing to match the city to the entire element not just the first item of the element. Can someone tell me how to get round that please?
The seocnd part is lets assume that city is found somewhere in citylist, how can I then increment the number next to the city name by 1?
Thanks for any guidance.
Use a dictionary or collections.Counter here. List is not an appropriate data-structure for this task.
Normal dictionary example:
citydict = {'New York': 53,
'San Francisco': 23,
'Los Angeles': 54}
Now simply update the dictionary like this:
for line in file_obj:
city = #do something with line
citydict[city] = citydict.get(city, 0) + 1
python dict is a proper data structure for what you want to achive. Using defaultdict(int) you can also increment directly for a given city (key of the dict) even if it is not yet present in the dict.
Use a dictionary to maintain the counters
Here is a sample code:
citydict = {}
all_cities = open("cities.txt", "r").readlines()
for city in all_cities:
if citydict.has_key(city):
citydict[city] +=1
else:
citydict[city] = 1
print citydict.items()
As everyone else said, a dictionay is exactly the datastructure for this type of problems. But if you really want it as list (e.g. to understand how lists work), you can do it as follows:
def add_to_citylist(citylist, city):
"""modifies citylist according to spec"""
city_already_in_citylist = False
#iterate throuch citylists and get city-sub-list as c:
for c in citylist:
if c[0] == city:
#city found, so update count
c[1] += 1
#take a note that city was in list:
city_already_in_citylist = True
if not city_already_in_citylist:
#we did not find city in citylist --> add it
citylist.append([city, 1])
#your citylist should be a list (not a tuple (...) ) since a tuple is unmutable
citylist = [['New York', 53], ['San Francisco', 23], ['Los Angeles', 54]]
add_to_citylist(citylist, "Boston")
add_to_citylist(citylist, "New York")
print citylist
After understanding the idea, you can improve the code by using "return" in the loop which has a similar effect but is more effective since it terminats the loop after the element is found:
def add_to_citylist(citylist, city):
"""modifies citylist according to spec"""
#iterate throuch citylists and get city-sub-list as c:
for c in citylist:
if c[0] == city:
#city found, so update count
c[1] += 1
break
citylist.append([city, 1])
I have a problem. I am new to django and trying to figure out how can I get specific values out of a list and a dict from views.py. I have the following dict output:
{'meta_title': u'Alaska State Fair Events', 'varos_id': 2886429L, 'longitude': -149.13053600000001, 'name': u'Palmer', 'thumbnail_id': 8406L, 'image': u'photologue/photos/2c18fe09-275b-4770-aab6-230cff72b2ee.jpg', 'orszag_id': u'US', 'helyszin': u'Alaska State Fair, 2075 Glenn Highway Palmer, AK 99645, United States ', 'slug': u'alaska-state-fair-palmer-ak', 'latitude': 61.580159999999999, 'allam_id': u'AK', 'nev': u'Alaska State Fair, Palmer, AK', 'id': 2886429L}
What I want to do is quite simple. I want to address the variables like image=szorakozohelyquery('image') which would result in
image=photologue/photos/2c18fe09-275b-4770-aab6-230cff72b2ee.jpg
Is there an easy way to do this? Also what is the easiest way to do this from a list?
d.get('image','default value') willprevent you from key error if key is not there in dictionary d
>>> d ={'image':'a.jpg'}
>>> d.get('image','not found')
'a.jpg'
>>> d={}
>>> d.get('image','not found')
'not found'
>>>
d['image'] will get you the value for key: 'image', from the dict: d.
... which will be: u'photologue/photos/2c18fe09-275b-4770-aab6-230cff72b2ee.jpg'.
"Also what is the easiest way to do this from a list?"
A list is a different data structure:
>>> my_list = ['a', 'b', 'c']
>>> print my_list[0]
a
see: http://docs.python.org/tutorial/datastructures.html for more info on lists and dicts.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Tuple value by key
How do i find the country name by having its code,
COUNTRIES = (
('AF', _(u'Afghanistan')),
('AX', _(u'\xc5land Islands')),
('AL', _(u'Albania')),
('DZ', _(u'Algeria')),
('AS', _(u'American Samoa')),
('AD', _(u'Andorra')),
('AO', _(u'Angola')),
('AI', _(u'Anguilla'))
)
I have code AS, find its name without using forloop on COUNTRIES tuple?
You can simply do:
countries_dict = dict(COUNTRIES) # Conversion to a dictionary mapping
print countries_dict['AS']
This simply creates a mapping between country abbreviations and country names. Accessing the mapping is very fast: this is probably the fastest method if you do multiple lookups, as Python's dictionary lookup is very efficient.
COUNTRIES = (
('AF', (u'Afghanistan')),
('AX', (u'\xc5land Islands')),
('AL', (u'Albania')),
('DZ', (u'Algeria')),
('AS', (u'American Samoa')),
('AD', (u'Andorra')),
('AO', (u'Angola')),
('AI', (u'Anguilla'))
)
print (country for (code, country) in COUNTRIES if code=='AD').next()
#>>> Andorra
print next((country for (code, country) in COUNTRIES if code=='AD'), None)
#Andorra
print next((country for (code, country) in COUNTRIES if code=='Blah'), None)
#None
# If you want to do multiple lookups, the best is to make a dict:
d = dict(COUNTRIES)
print d['AD']
#>>> Andorra
You can't.
Either
[x[1] for x in COUNTRIES if x[0] == 'AS'][0]
or
filter(lambda x: x[0] == 'AS', COUNTRIES)[0][1]
but these are still "loops".