Get max value in Python in case of tiebreaker - python

I would like to know of a way to get the reverse alphabetical order item in the case of a tiebreaker using max(lst,key=lst.count) or if there is a better way.
For example if I had the following list:
mylist = ['fire','water','water','fire']
Even though both water and fire occur twice, I would like it to return 'water' since it comes first in the reverse alphabetical order instead of it returning the first available value.

I created a function that gets the max value based on two keys, being one primary and one secondary.
Here it is:
def max_2_keys(__iter: iter, primary, secondary):
srtd = sorted(__iter, key=primary, reverse=True)
filtered = filter(lambda x: primary(x) == primary(srtd[0]), srtd)
return sorted(filtered, key=secondary, reverse=True)[0]
in your case, you can execute the following lines:
from string import printable
max_2_keys(lst,primary=lst.count, secondary=lambda x: printable[::-1].index(x[0]))
```

Related

How to sort a list of tuples based on the 2nd value without hardcoding it

I have a list of tuples.
[('first_title', 'first_content','notes'),('second_title','second_content','Lists'), ('third_title', 'third_content','Books'), ('fourth_title', 'fourth_content','Chores')
and I want to get each tuple in the code and place them in a list where that list has only the tuples that have the same 2nd value (starting at 0) but without hardcoding what the second value or the length of the list.So the result would look like...
notes = [('first_title, 'first_content, 'notes')]
Lists = [('second_title, 'second_content, 'Lists')]
Books = [('third_title, 'third_content, 'Books')]
Chores = [('fourth_title, 'fourth_content, 'Chores')]
so I can't really do...
if x[2] == 'Lists'
because it's hardcoded.
If there was another tuple that had the 2nd element (starting at 0) equal to 'Books' then it would be in the Books list for example.
You want to create a dictionary of lists where the third value in each tuple is used as key.
You can use a defaultdict to create a new list automatically when a key is inserted for the first time:
from collections import defaultdict
result = defaultdict(list)
for item in list_of_tuples:
key = item[2]
result[key].append(item)
Now you can use result['notes'], result['Lists'], etc.
Seems like you are looking for filter?
This would allow you to reuse some of the code like this (throw in a selector if you want to be even more flexible but not required):
inp = [('first_title', 'first_content','notes'),('second_title','second_content','Lists'), ('third_title', 'third_content','Books'), ('fourth_title', 'fourth_content','Chores')]
def get_by(category, l, selector=lambda x: x[2]):
return filter(l, lambda x: selector(x) == category)
I can then get the categories:
get_by('Books', inp)
Or I can change the selector and filter on some other criteria:
get_by('first_title', inp, selector=lambda x: x[0])

Python Max function - Finding highest value in a dictionary

My question is about finding highest value in a dictionary using max function.
I have a created dictionary that looks like this:
cc_GDP = {'af': 1243738953, 'as': 343435646, etc}
I would like to be able to simply find and print the highest GDP value for each country.
My best attempt having read through similar questions is as follows (I'm currently working through the Python crash course book at which the base of this code has been taken, note the get_country_code function is simply providing 2 letter abbreviations for the countries in the GDP_data json file):
#Load the data into a list
filename = 'gdp_data.json'
with open(filename) as f:
gdp_data = json.load(f)
cc_GDP` = {}
for gdp_dict in gdp_data:
if gdp_dict['Year'] == 2016:
country_name = gdp_dict['Country Name']
GDP_total = int(gdp_dict['Value'])
code = get_country_code(country_name)
if code:
cc_GDP[code] = int(GDP_total)
print(max(cc_GDP, key=lambda key: cc_GDP[key][1]))
This provides the following error 'TypeError: 'int' object is not subscriptable'
Note if leaving out the [1] in the print function, this does provide the highest key which relates to the highest value, but does not return the highest value itself which is what I wish to achieve.
Any help would be appreciated.
So you currently extract the key of the country that has the highest value with this line:
country_w_highest_val = max(cc_GDP, key=lambda key: cc_GDP[key]))
You can of course just look that up in the dictionary again:
highest_val = cc_GDP[contry_w_highest_val]
But simpler, disregard the keys completely, and just find the highest value of all values in the dictionary:
highest_val = max(cc_GDP.values())
How about something like this:
print max(cc_GDP.values())
That will give you the highest value but not the key.
The error is being cause because you need to look at the entire dictionary, not just one item. remove the [1] and then use the following line:
print(cc_GDP[max(cc_GDP, key=lambda key: cc_GDP[key])])
Your code currently just returns the dictionary key. You need to plug this key back into the dictionary to get the GDP.
You could deploy .items() method of dict to get key-value pairs (tuples) and process it following way:
cc_GDP = {'af': 1243738953, 'as': 343435646}
m = max(list(cc_GDP.items()), key=lambda x:x[1])
print(m) #prints ('af', 1243738953)
Output m in this case is 2-tuple, you might access key 'af' via m[0] and value 1243738953 via m[1].

How to get 'specific' keys with maximum value in dictionary?

My dict is:
rec_Dict = {'000000000500test.0010': -103,
'000000000500test.0012': -104,
'000000000501test.0015': -105,
'000000000501test.0017': -106}
I know how to find maximum value:
>>print 'max:' + str(max(recB_Dict.iteritems(), key=operator.itemgetter(1)))
max:(u'000000000500test.0010', -103)`
But I want to find keys beginning with '000000000501test', but not including '000000000501test.0015' or any starting with '000000000500test'.
It should print like:
max:(u'000000000501test.0015', -105)`
How can I use keyword to get?
I can't understand the conditions you want to filter keys, but you can use the below scripts (just fix the conditions)
genetator_filter = genetator_filter = ((a,b) for a,b in rec_Dict.iteritems() if (not '.0015' in a) and (not '000000000500test.' in a) )
#(you need to fix filter conditions for keys)
print 'max:' + str(max(genetator_filter, key = lambda x:x[1]))
Separating responsibility to achieve the final result, you can find your max based on what you are looking to match on exactly. Then using that max, just output the value. Granted, some will argue that it is not the most optimized, or not the most functional way to go about it. But, personally, it works just fine, and achieves the result with good enough performance. Furthermore, makes it more readable and easy to test.
Get the max based on the part of the string you want by extracting keys and finding the max:
max_key_substr = max(i.split('.')[0] for i in rec_Dict)
Iterate with that max_key_substr and output the key/value pair:
for key, value in rec_Dict.items():
if max_key_substr in key:
print(key, value)
The output will be:
000000000501test.0015 -105
000000000501test.0017 -106
What you say it should print like doesn't make sense because the key '000000000501test.0015'should have been excluded according to other things you said.
Ignoring that, you could use a generator expression to sift-out the items you don't want processed:
from operator import itemgetter
rec_Dict = {'000000000500test.0010': -103,
'000000000500test.0012': -104,
'000000000501test.0015': -105,
'000000000501test.0017': -106}
def get_max(items):
def sift(record):
key, value = record
return key.startswith('000000000501') and not key.endswith('.0015')
max_record = max((item for item in items if sift(item)), key=itemgetter(1))
return max_record
print(get_max(rec_Dict.iteritems())) # -> ('000000000501test.0017', -106)

How can I sort list of strings in specific order?

Let's say I have such a list:
['word_4_0_w_7',
'word_4_0_w_6',
'word_3_0_w_10',
'word_3_0_w_2']
and I want to sort them according to number that comes after "word" and according to number after "w".
It will look like this:
['word_3_0_w_2',
'word_3_0_w_10',
'word_4_0_w_6',
'word_4_0_w_7']
What comes in mind is to create a bunch of list and according to index after "word" stuff them with sorted strings according "w", and then merge them.
Is in Python more clever way to do it?
Use Python's key functionality, in conjunction with other answers:
def mykey(value):
ls = value.split("_")
return int(ls[1]), int(ls[-1])
newlist = sorted(firstlist, key=mykey)
## or, if you want it in place:
firstlist.sort(key=mykey)
Python will be more efficient with key vs cmp.
You can provide a function to the sort() method of list objects:
l = ['word_4_0_w_7',
'word_4_0_w_6',
'word_3_0_w_10',
'word_3_0_w_2']
def my_key_func(x):
xx = x.split("_")
return (int(xx[1]), int(xx[-1]))
l.sort(key=my_key_func)
Output:
print l
['word_3_0_w_2', 'word_3_0_w_10', 'word_4_0_w_6', 'word_4_0_w_7']
edit: Changed code according to comment by #dwanderson ; more info on this can be found here.
You can use a function to extract the relevant parts of your string and then use those parts to sort:
a = ['word_4_0_w_7', 'word_4_0_w_6', 'word_3_0_w_10', 'word_3_0_w_2']
def sort_func(x):
parts = x.split('_');
sort_key = parts[1]+parts[2]+"%02d"%int(parts[4])
return sort_key
a_sorted = sorted(a,key=sort_func)
The expression "%02d" %int(x.split('_')[4]) is used to add a leading zero in front of second number otherwise 10 will sort before 2. You may have to do the same with the number extracted by x.split('_')[2].

How do you sort a list of numbers in descending order

Say I've got a file with multiple names and integers like so:
name1:5
name2:3
name3:10
How can I add this to a dictionary, and then print it in descending order (eg highest value to lowest value)
Assuming by list you meant dict, this is what you want:
names={'name1':5, 'name2':3, 'name3':10}
print sorted(names, key=lambda x:names[x], reverse=True)
As another poster pointed out, the original poster requested to print out both the name & it's value. To accomplish this, change the code to:
names={'name1':5, 'name2':3, 'name3':10}
for name in sorted(names, key=lambda x:names[x], reverse=True):
print name, names[name]
You need to specify an appropriate key function for the builtin sorted:
# I assume this is what your input looks like
input = ["name1:5", "name2:3", "name3:10"]
output = sorted(input, key=lambda x: int(x.split(":")[1]), reverse=True)
i got your point what you are saying and how it is done is given below :)
a=[name1:5, name2:3, name3:10]
def Last(s):
return s[-1]
sorted(a, key=Last)
and then in this way you can sort it in reverse ..as per your choice ..enjoy :)

Categories