Python Return Max Dictionary Entry - python-3.x

I have a defaultdict that is storing the count of names that appear in a list. The dictionary is as follows:
{"John": 5, "Jim": 2, "Zack": 1, "Brian": 5, "Tim": 3}
How can I efficiently return a dictionary that only contains the max value? In this case, since there is a tie, I'm looking for the final result to be:
{"John": 5, "Brian": 5}
I know I could loop through the original dictionary to accomplish this but I'm curious if there is a more pythonic way to go about it.

You can use this as a method to select only the maximum values:
dict1 = {"John": 5, "Jim": 2, "Zack": 1, "Brian": 5, "Tim": 3}
max1 = max(dict1.values())
dict2 = dict(filter(lambda elem: elem[1] == max1, dict1.items()))
print(dict2)
Basically, it first finds out the maximum value out of the dictionary and then filters out the entries which match with the highest value.

mm = {"John": 5, "Jim": 2, "Zack": 1, "Brian": 5, "Tim": 3}
def keys_with_top_values(my_dict):
return [key for (key, value) in my_dict.items() if value == max(my_dict.values())]
print(keys_with_top_values(mm))

Related

Sorting lists of floats

I would like to sort the list s and in the same manner the list s1. The code below workers for integers (after changing 2.2 to 2 and 20.6 to 20). How to adjust the code for floats, please?
s = [2.2, 3, 1, 4, 5, 3]
s1 = [20.6, 600, 10, 40, 5000, 300]
res = []
for i in range(len(s1)):
res0 = s1[s[i]]
res.append(res0)
print(res)
print('Sorted s:', sorted(s))
print('Ind:', sorted(range(len(s)), key=lambda k: s[k]))
print('s1 in the same manner as s:', res)
There is actually an error related with a part of your code res0 = s1[s[i]] that pops up:
list indices must be integers or slices, not float.
Supposed that the index is 0: s1[s[0]] -> s[0] == 2.2 -> s1[2.2]
Your code is actually using the values of s as an index for each value of s1. Your code wouldn't be able to sort a list by the manner of another list regardless if the list contains integers only.
Instead, you should add two new arrays:
s_index_list = sorted(range(len(s)), key=lambda k: s[k])
s1_sorted = sorted(s1)
One which contains the index of each value of s (Reference to this answer https://stackoverflow.com/a/7851166/18052186), and another which sort s1.
Then, you replace this bit of your code.
res0 = s1[s[i]]
by
res0 = s1_sorted[s_index_list[i]]
That way, you can sort the list s1 in the same manner as s by actually associating a value of s1 with an index from s. The result would have been:
[40, 10, 20.6, 5000, 300, 600]
Sorted s: [1, 2.2, 3, 3, 4, 5]
Ind: [2, 0, 1, 5, 3, 4]
s1 in the same manner as s: [40, 10, 20.6, 5000, 300, 600]

Python: Is it possible to do the same using reduce()?

This is part of an assaigment so it needs to be donde using the reduce function (or filter although I don't see it), hence I'd like to know if it's possible.
I have two dicts:
takeOff_Airport = {'LPPD': 4, 'DAAS': 1, 'EDDH': 16, 'LFLL': 17, 'LFPO': 30}
landing_Airport = {'LFPO': 12, 'LPPD': 7, 'UUEE': 11, 'DAAS': 7, 'LFSL': 1}
After applying the follwing code:
airports = (sorted([[k, [v1+landing_Airport[k], v1,landing_Airport[k]]] for k,
v1 in takeOff_Airport.items() if k in landing_Airport],
key=lambda kv:kv[1], reverse=True))
I get the expected result:
airports: [['LFPO', 42, 30, 12], ['LPPD', 11, 4, 7], ['DAAS', 8, 1, 7]]
What 'airports' is printing is a list of lists with the common airport names in both dictionaries (landing and takeoff) and adding the sum of each dict value as well as each of the dictionaries [key:value ].
Is it possible to implement the above using some lambda expression in a reduce function? Maybe in a filter?
It is definitely possible.
The lambda takes as arguments the array x which aggregates the result and the key into one of the airports dictionaries (takeOff_Airport in my example).
If the key exists in the other airport dictionary, then the element formed by [key, sum of each dict value, takeOff value, landing value] is added to the array x. Else, array x is left unchanged.
Pass the lambda into the reduce function, setting the initial value of x to an empty array and it will generate the desired result.
airports = reduce(lambda x, key : x + [[key, takeOff_Airport[key] + landing_Airport[key], takeOff_Airport[key], landing_Airport[key]]] if key in landing_Airport else x, takeOff_Airport, [])
Result:
>>> airports
[['LPPD', 11, 4, 7], ['DAAS', 8, 1, 7], ['LFPO', 42, 30, 12]]

Using enumerate within a dictionary comprehension of a nested list

Is there an elegant/pythonic method for creating a dictionary from a nested list with enumerate, that enumerates at the sublist level rather that at the list-of-lists level?
Please consider this example:
nested_list = [["ca", "at"], ["li", "if", "fe"], ["ca", "ar"]]
I have tried to convert it into a dictionary that looks like this:
# Desired output.
# {'ca': 0, 'at': 1, 'li': 2, 'if': 3, 'fe': 4, 'ar': 5}
Here is my best attempt, but it appears to enumerate the list at the upper level and overwrite the value for duplicate keys - which is undesirable.
item_dict = {item: i for i, item in enumerate(nested_list) for item in item}
# Current output.
# {'ca': 2, 'at': 0, 'li': 1, 'if': 1, 'fe': 1, 'ar': 2}
Am I better off splitting this task into an un-nesting step, and then a dictionary comprehension step?
All insight is appreciated, thank you.
Using itertools.chain
Ex:
from itertools import chain
nested_list = [["ca", "at"], ["li", "if", "fe"], ["ca", "ar"]]
result = {}
c = 0
for i in chain.from_iterable(nested_list):
if i not in result:
result[i] = c
c += 1
print(result)
Output:
{'ca': 0, 'at': 1, 'li': 2, 'if': 3, 'fe': 4, 'ar': 5}
I think I've solved it, but it's quite ugly...
{key: i for i, key in enumerate(set([item for item in nested_list for item in item]))}
# Output.
{'if': 0, 'at': 1, 'fe': 2, 'li': 3, 'ca': 4, 'ar': 5}

Can you use count() for an entire list instead of one variable?

Is there a way to use count() for an entire list rather than have to use it on each variable seperately? If this is possible it would save me alot of typing.
var1 = random.randint(u,v)
var2 = random.randint(w,x)
var3 = random.randint(y,z)
listName = [var1,var2,var3]
listName.count(x)
listName.count(y) #can you get the count for an entire list instead of having to do them
listName.count(z) #all seperately? It would be much more efficient.
Here's an example of creating a list with random contents and then showing the length and sum.
import random
my_list = [
random.randint(1, 10),
random.randint(1, 10),
random.randint(1, 10)
]
print("The value of my_list is {0}".format(my_list))
print("The length of my_list is {0}".format(len(my_list)))
print("The sum of my_list is {0}".format(sum(my_list)))
Sample Output:
The value of my_list is [4, 8, 4]
The length of my_list is 3
The sum of my_list is 16
Is this what you were looking for?
list.count(item) returns the number of times item appears in a list.
If you want to know how many times each item appears in the list, if it appears in the list, you can do this:
original_list = [1, 1, 2, 3, 4, 4, 4]
uniques = list(set(original_list))
counts = {}
for unique in uniques:
counts[unique] = original_list.count(unique)
print(counts)
which should print something like
{
1: 2,
2: 1,
3: 1,
4: 3
}
Here's more info on the set data type:
https://docs.python.org/3/tutorial/datastructures.html#sets
While we're at it, you can also use collections.Counter:
from collections import Counter
counts = Counter([1, 1, 2, 3, 4, 4, 4])
print(dict(counts))
and this should print the same dictionary as above.

Checking whether a list of numbers contains ANY five number sequence

I have a list that only includes positive integers:
my_list = [1, 2, 4, 7, 9, 10, 15, 16]
The list is sorted.
What would be the most "pythonic" way to check whether the list contains any sequence of x consequtive number? It shouldn't matter whether the sequence starts at the beginning of the list, or ends at the end of the list - as long as it's in the list, it should return true. For instance, if I wanted to check if the following list contains a 4-number sequence:
my_list = [1, 3, 4, 5, 6, 8, 10]
It should return true due to [3, 4, 5, 6]
I have seen multiple StackOverflow questions about "finding number sequences in lists", however none of them dealt with looking for a sequence in only a portion of the list. (What I found was useful only if the goal was to check whether the entire list is sequential.)
Here's a one liner:
def has_sequence(L, seq_len):
return any(list(L[i:i+seq_len]) == list(range(L[i],L[i]+seq_len))
for i in range(len(L)-seq_len+1))
def findRun(L, n):
runlen = 0
for i in range(1, len(L)):
if L[i] == L[i-1]+1:
runlen += 1
else:
runlen = 0
if runlen == n-1:
print("Found a run starting at", i-n+1)
Output:
In [451]: L = [1, 3, 4, 5, 6, 8, 10]
In [452]: findRun(L, 4)
Found a run starting at 1
You can try this:
after grouping them with the difference, you just check if any of the groups contains your preferred number of consecutive sequence(in this case 4).
from itertools import groupby
from operator import itemgetter
my_list = [1, 3, 4, 5, 6, 8, 10]
check = False
for key, group in groupby(enumerate(my_list), lambda (i, val): i - val):
g = map(itemgetter(1), group)
if len(g) == 4:
check = True
print(check)
True
I hope this is what you looking for.

Resources