Getting an element from tuple of tuples in python [duplicate] - python

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".

Related

Finding highest value in a dictionary

I'm new to programming and currently taking a CSC 110 class. Our assignment is to create a bunch functions that do all sorts of things with some data that is given. I have taken all that data and put it into a dictionary but I'm having some trouble getting the data I want out of it.
Here is my problem:
I have a dictionary that stores a bunch of countries followed by a list that includes their population and GDP. Formatted something like this
{'country': [population, GDP], ...}
My task is to loop through this and find the country with the highest population or GDP then print:
'The country with the highest population is ' + highCountry+\
' with a population of ' + format(highPop, ',.0f')+'.')
In order to do this I wrote this function (this one is specifically for highest population but they all look about the same).
def highestPop(worldInfo):
highPop = worldInfo[next(iter(worldInfo))][0] #Grabs first countries Population
highCountry = next(iter(worldInfo))#Grabs first country in worldInfo
for k,v in worldInfo.items():
if v[0] > highPop:
highPop = v[0]
highCountry = k
return highPop,highCountry
While this is working for me I gotta think there is an easier way to do this. Also I'm not 100% sure how [next(iter(worldInfo))] works. Does this just grab the first value it sees?
Thanks for your help in advance!
Edit: Sorry I guess I wasn't clear. I need to pass the countries population but also the countries name. So I can print both of them in my main function.
I think you're looking for this:
max(worldInfo.items(), key=lambda x: x[1][0])
This will return both the country name and its info. For instance:
('france', [100, 22])
The max() function can work on python "iterables" which is a fancy word for anything that can be cycled or looped through. Thus it cycles or loops through the thing you put into it and spits out the item that's the highest.
But how does it judge which tuple is highest? Which is higher: France or Germany? You have to specify a key (some specification for how to judge each item). The key=lambda etc specifies a function that given an item (x), judge that item based on x[1][0]. In this instance if the item is ('france', [100, 22]) then x[1][0] is 100. So the x[1][0] of each item is compared and the item with the highest one is returned.
The next() and iter() functions are for python iterators. For example:
mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)
print(next(myit)) #=> apple
print(next(myit)) #=> banana
print(next(myit)) #=> cherry
Use the max() function, like so:
max(item[0] for item in county_dict.values()) #use item[1] for GDP!
Also try storing the values not in a list ([a, b]) but in a tuple ((a, b)).
Edit: Like iamanigeeit said in the comments, this works to give you the country name as well:
max(data[0], country for country, data in country_dict.items())
An efficient solution to get the key with the highest value: you can use the max function this way:
highCountry = max(worldInfo, key=lambda k: worldInfo[k][0])
The key argument is a function that specifies what values you want to use to determine the max.max(data[0], country for country, data in country_dict.items())
And obviously :
highPop = worldInfo[highCountry][0]

Using a dict as a key when not all values exist [duplicate]

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.

Append or Add to string of specific index

I have a list of class objects 'x'. I am trying to create a new list by appending certain attribute values of the objects but I would like to append more that one attribute per index. For example, what I currently get:
x = blah.values()
newList = []
for i in range(len(x)):
if x[i].status == 'ACT':
newList.append(str(x[i].full_name)),
newList.append(str(x[i].team))
else:
pass
print newList
The above code provides me with something like:
['Victor Cruz', 'NYG', 'Marcus Cromartie', 'SF',....]
What I am trying to get:
['Victor Cruz NYG', 'Marcus Cromartie SF',....]
How can I append more than one attribute per index? Hope this make sense, I can try to further elaborate if needed, thanks!
You can use .format() in order to format your string. Notice the space between {} {}
for i in range(len(x)):
if x[i].status == 'ACT':
newList.append("{} {}".format(x[i].full_name,x[i].team) )
Another way is using "%s" % string notation
newList.append("%s %s" % (str(x[i].full_name),str(x[i].team)))
Another example of .format using.
"{} is {}".format('My answer', 'good')
>>> "My answer is good"
You could put the items into one string using .format() and append the string once:
for i in range(len(x)):
if x[i].status == 'ACT':
newList.append('{} {}'.format(x[i].full_name, x[i].team))
On a lighter note, using a list comprehension is a great alternative for creating your list:
newList = ['{} {}'.format(o.full_name, o.team) for o in blah.values() if o.status == 'ACT']
You'll notice that range and len are no longer used in the comprehension, and there is no longer need for indexing.

How to use string value as a variable name in Python? [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 6 years ago.
Suppose I have lists as follows:
candy = ['a','b','c']
fruit = ['d','e','f']
snack = ['g','h','i']
and a string
name = 'fruit'
I want to use string name for accessing list and it's content. In this case it should be fruit. I will use name for iterating list. As:
for x in name:
print x
You can use globals() like so:
for e in globals()[name]:
print(e)
Output:
d
e
f
And if your variables happen to be in some local scope you can use locals()
OR you can create your dictionary and access that:
d = {'candy': candy, 'fruit': fruit, 'snack': snack}
name = 'fruit'
for e in d[name]:
print(e)
I don't understand what exactly you're trying to achieve by doing this but this can be done using eval. I don't recommend using eval though. It'd be better if you tell us what you're trying to achieve finally.
>>> candy = ['a','b','c']
>>> fruit = ['d','e','f']
>>> snack = ['g','h','i']
>>> name = 'fruit'
>>> eval(name)
['d', 'e', 'f']
EDIT
Look at the other answer by Sнаđошƒаӽ. It'll be better way to go. eval has security risk and I do not recommend its usage.
Use a dictionary!
my_dictionary = { #Use {} to enclose your dictionary! dictionaries are key,value pairs. so for this dict 'fruit' is a key and ['d', 'e', 'f'] are values associated with the key 'fruit'
'fruit' : ['d','e','f'], #indentation within a dict doesn't matter as long as each item is separated by a ,
'candy' : ['a','b','c'] ,
'snack' : ['g','h','i']
}
print my_dictionary['fruit'] # how to access a dictionary.
for key in my_dictionary:
print key #how to iterate through a dictionary, each iteration will give you the next key
print my_dictionary[key] #you can access the value of each key like this, it is however suggested to do the following!
for key, value in my_dictionary.iteritems():
print key, value #where key is the key and value is the value associated with key
print my_dictionary.keys() #list of keys for a dict
print my_dictionary.values() #list of values for a dict
dictionaries by default are not ordered, and this can cause problems down the line, however there are ways around this using multidimensional arrays or orderedDicts but we will save this for a later time!
I hope this helps!

Searching and manipulating lists in lists in Python

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])

Categories