Getting lowest non-zero value from a dictionary - python-3.x

I am trying to get the largest and smallest value / values from a dictionary.
Where the lowest value should not be zero, but the closest to it.
If there is a 0 present and the values are K:0 K:3 K:7 K:1 it should return 1 and not 0.
I've tried using the min / max functions, but haven't been able to get them to work properly. Want to get all values even when there are multiple.
Example Dictionary.
Dict = {"D1" : "0", "D2" : "2", "D3" : "7", "D4" : "7", "D5" : "4"}
Highest = max(Dict, key=Dict.get)
Lowest = min(Dict, key=Dict.get)
Only gets me D3 and D1 respectively. Also returns the 0.
Highest works in most cases, but Lowest returns the 0. Should there be a check after lowest has been assigned and iterate over the dictionary again?
Highest and Lowest can be a list or a single Value doesn't really matter.
My current code looks something like this.
Dict = {"D1" : "0", "D2" : "2", "D3" : "7", "D4" : "7", "D5" : "4"}
Highest = max(Dict, key=Dict.get)
Lowest = min(Dict, key=Dict.get)
for key, value in Dict.items():
if value == Dict[Highest]:
Do x
elif value == Dict[Lowest]:
Do y
else:
Do z
Which mostly works, except for the above mentioned 0 getting returned.
Edit
Was doing some more testing and the dictionaries received had a chance to be full of zero values or the same positive integer.
Which made the solution a bit wonky.
Decided to change it up a bit and iterate over the items instead by assigning a start value for both highest and lowest.
When iterating through the dictionary I assigned new values to highest and lowest if they were either > or < respectively.
Something like the code below. (Tried to comment with some code, but the formatting got messed up, so decided to edit the question a bit instead).
Highest = -1
Lowest = 1000000 # Highest Value the dictionary values may have
for key in dict:
if dict[key] > Highest and dict[key] != 0:
Highest = dict[key]
if dict[key] < Lowest and dict[key] != 0:
Lowest = dict[key]
# Then possible to iterate over the dictionary and get the highest and lowest values from the dictionary.
for key, value in dict.items():
if value == Highest and Highest != -1:
Do X
elif value != 0:
if value == Lowest and Lowest != 1000000:
Do Y
else:
Do z
else:
Do z

You need to filter first, then min/max the filtered data. Sticking to your design as closely as possible:
nozeroes = {k: v for k, v in Dict.items() if v > 0} # New dict with only positive values
# Only change to original version is replacing Dict with nozeroes
Highest = max(nozeroes, key=Dict.get)
Lowest = min(nozeroes, key=Dict.get)
Note: If you just want the values themselves, and don't care about the keys, this is even easier:
nonzero_values = [v for v in Dict.values() if v > 0]
Highest = max(nonzero_values)
Lowest = min(nonzero_values)

from math import inf
Dict = {"D1": "0", "D2": "2", "D3": "7", "D4": "7", "D5": "4"}
Highest = max(Dict, key=lambda x: Dict[x] or inf)
Lowest = min(Dict, key=lambda x: Dict[x] or inf)

Related

sum the values of dictionary only if the keys is equal or greater than x

Given a dictionary which contains keys and values, and I want sum the values based on the keys value. For example, {1:10, 2:20, 3:30, 4:40, 5:50, 6:60}, and sum the values only if is equal or greater than 2 in keys, which output is 200.
x =2
count = 0
for key, value in dictionary.items():
while key == x:
count += 1[value]
And my output is none, and I don't know what I am missing on.
Try this. Your way of iterating over the dictionary items is correct, but inside the loop, you need to check if the current key is greater than or equal to your required key. Only then you should increment the count with the value corresponding to that key which can be retrieved in this way - dictionary[key] or you can simply add the value like count+=value
dictionary = {1:10, 2:20, 3:30, 4:40, 5:50, 6:60}
x=2
count = 0
for key,value in dictionary.items():
if key>=x:
count += dictionary[key]
print(count)
your code is incomplete and won't run as-is, so it's difficult to speculate why you're getting an output of None.
in your requirements you mention "equal or greater than 2" but your code has "key == x". This should be "key >= x".
inside your for loop you have a while. Fixing other issues this would result in an infinite loop. You want an if, not a while.
fixing those things and making an assumption or two, your code would be:
x = 2
count = 0
for key, value in dictionary.items():
if key >= x:
count += value
Alternately, you could write it in a single line of code:
sum ( v for k, v in dictionary.items() if k >= x )
I believe you just need to do as below:
count = 0
for key, value in dictionary.items():
if key >= n:
count += value

How to compare character frequency and return the most occurring character?

I am trying to build a function which returns the most occurred character in a given string and it's working pretty nicely, but how do I return None if the characters have same frequency?
Like for input: 'abac'
Expected output is: 'a'
and for input: 'abab'
Expected output is: None
I have tried using a dictionary to store character frequency and then returning the element with largest value.
def most_occuring_char(str1):
count = {}
max = 0
c = ''
for char in str1:
if char in count.keys():
count[char]+=1
else:
count[char] = 1
for char in str1:
if max < count[char]:
max = count[char]
c = char
return c
I don't know how to check whether the count dictionary elements have same frequency.
You can do that counting with the dict using collections.Counter.
You basically only have to add a check to see if the maximum count is unique (if so, return the char with maximum number of occurrences) or not (if so, return None):
from collections import Counter
def most_occurring_char(string):
counter = Counter(string)
max_char_count = max(counter.values())
is_unique = len([char_count for char_count in counter.values() if char_count == max_char_count]) == 1
if is_unique:
char = [char for char, count in counter.items() if count == max_char_count][0]
return char
return None
# Tests
assert most_occurring_char('abac') == 'a'
assert most_occurring_char('abab') is None
Once you have a dictionary containing the counts of every character (after your first for loop), you can inspect this to determine whether certain counts are the same or not.
If you wish to return None only when all the character counts are the same, you could extract the values (i.e. the character counts) from your dictionary, sort them so they are in numerical order, and compare the first and last values. Since they are sorted, if the first and last values are the same, so are all the intervening values. This can be done using the following code:
count_values = sorted(count.values())
if count_values[0] == count_values[-1]: return None
If you wish to return None whenever there is no single most frequent character, you could instead compare the last value of the sorted list to the second last. If these are equal, there are two or more characters that occur most frequently. The code for this is very similar to the code above.
count_values = sorted(count.values())
if count_values[-1] == count_values[-2]: return None
Another possibility:
def most_occuring_char(s):
from collections import Counter
d = Counter(s)
k = sorted(d, key=lambda x:d[x], reverse=True)
if len(k) == 1: return k[0]
return None if len(k) == 0 or d[k[0]] == d[k[1]] else k[0]
#Test
print(most_occuring_char('abac')) #a
print(most_occuring_char('abab')) #None (same frequencies)
print(most_occuring_char('x')) #x
print(most_occuring_char('abcccba')) #c
print(most_occuring_char('')) #None (empty string)

Counting pairs of numbers that adds up to a specific value in Python

i want to count how many pairs of numbers in a list can add to a specific number, this is my code in python but the output is not what it should be
list = [1,2,3,4]
x=3
count = 0
for i in range(len(list)):
for j in range(len(list)):
if i + j == x:
count+=1
print(count)
You could simpilify your code with functions from the built-in itertools module, depending on how you would like to iterate through the list, i.e. combinations, combinations with replacements, or products.
import itertools as itt
in_list = [1,2,3,4]
tgt_num = 3
count = 0
for a,b in itt.combinations(in_list, 2): # returns 1
# for a,b in itt.combinations_with_replacement(in_list, 2): # returns 1
# for a,b in itt.product(in_list, in_list): # returns 2
if a + b == tgt_num:
count += 1
print(count)
Your code has some issues:
One is that it never directly references the items of the list. Because of this, it will only work assuming that the numbers in the list are in ascending order, each is one apart, and that it starts at 1.
Another is that it iterates through the pairs of numbers too many times.
Finally, there are some indentation issues, but I'm guessing those were just lost in the copy-paste. I tried to re-indent it, but when I ran it I got "4", when it should be "1".
Here's a version that incorporates indexing the list, which should resolve the above issues.
list = [1,2,3,4]
x = 3
count = 0
for i in range(0,len(list)):
pair1 = list[i]
pair2 = list[i+1:]
for j in range(0,len(pair2)):
if pair1 + pair2[j] == x:
count += 1
print(count)

Return False if the same input is given more than once

I want to return False if the same input is given:
first_answer = input("select square number 1: ")
second_answer = input("select square number 2: ")
third_answer = input("select square number 3: ")
if first_answer == second_answer or first_answer == third_answer or
second_answer == first_answer or second_answer == third_answer or
third_answer == first_answer or third_answer == second_answer:
print("don\'t repeat squares")
Is there an easier way?
Do you like this:
set_answers = set()
set_answers.add(input("select square number 1: "))
set_answers.add(input("select square number 2: "))
set_answers.add(input("select square number 3: "))
if len(set_answers) < 3:
print("don\'t repeat squares")
?
The TRICK: set() stores only unique elements, so adding same value again to a set doesn't change the number of its elements.
Try this.
count = 3
answers = []
for i in range(0, count):
answers[i] = input("select square number " + str(i+1) + ": "
for i in range(0, count-1):
for j in range(i+1, count):
if answers[i] == answers[j]:
print("don\'t repeat squares")
It is (almost) always easier to abstract this kind of thing by using loops and arrays (or sets, or tuples) than to program each variable by hand.
answers is a list here, and the first loop inputs the data into the array. Note that you can easily change the amount of data you want simply by modifying the initial value of count -- this will change everything else as well (including the input messages!).
The second loop is actually a nested pair of for loops in order to generate all of the (relevant) pairs of data items to compare. Note that the first loop stops one short of the last element and that the second loop starts one after whatever the value of the first loop is. This is in order to avoid incorrectly comparing an element with itself.
CLARIFICATION:
[] is an empty list. A list in Python is just an ordered list of elements that can be accessed by their position (index) in the list. Indexes start from 0. (there are good reasons for this)
In general, the range function returns all the integers in the given range that includes the lower bound (the left argument) and does not include the upper bound (the right argument). (there are good reasons for this too)

How to retrieve the max key and max value from a dictionary?

a = ['also', 'akin', 'akee','ague', 'aero', 'anes','here','beer','bute', 'byre', 'came', 'case', 'doze', 'down', 'drek', 'drew', 'dyes', 'fret', 'freo']
i = 'e'#i is user guess input
dic = {}
for item in a:
key = ''
for chr in item:
if chr == i:
key += i
else:
key += '-'
if key not in dic:
dic[key] = []
dic[key].append(item)
print(dic)
c = max(k for k, v in dic.items())
d = max(v for k, v in dic.items())
print('\nmax key:',c)
print('\nmax value:',d)
Output:
{'---e': ['ague', 'bute', 'byre', 'came', 'case', 'doze'], '--ee': ['akee'], '----': ['also', 'akin', 'down'], '-e-e': ['here'], '-ee-': ['beer'], '--e-': ['anes', 'drek', 'drew', 'dyes', 'fret', 'freo'], '-e--': ['aero']}
max key: -ee-
max value: ['here']
In the above example, a is a list of words. When the user guess a letter, for example 'e', the program iterates through each word in the list. Replace any letter that is not 'e' to a dash '-'.
I tried to map that result into a dictionary to keep track of the each group of words that where letter 'e' occurs in the same position.
Now, i want to retrieve the group of words(or key) with the largest number of words. Judging by the output, i'm not doing that because key'-e--' has the largest number of words.
I've also tried
max(dic.keys())
max(dic)
dic.get(max(dic.keys()))
Am i not fully understand the concept of max key and values for a dictionary?
Please suggest how i can fix this.
Thanks
In your question, the notion of max means being associated with the largest list., or being the largest list
max(dic.keys(), key=lambda x: len(dic[x]))
Will give you the maximum of dic's keys
Also,
sorted(dic.items(), key=lambda x:len(x[1]), reverse=True)
(in this example, lambda (x, y): len(y) works in python 2, not sure about python 3)
Will output a list of key, value tuples sorted by number of matches:
[('---e', ['ague', 'bute', 'byre', 'came', 'case', 'doze']), ('--e-', ['anes', 'drek', 'drew', 'dyes', 'fret', 'freo']), ('----', ['also', 'akin', 'down']), ('-e-e', ['here']), ('--ee', ['akee']), ('-e--', ['aero']), ('-ee-', ['beer'])]
Edit, no lambda
Without using a lambda, you'd be using a regular function:
def myMax(value_tuple):
key, value = value_tuple
return len(value)
and using it like so:
max(dic.items(), key=myMax)
Retrieve max key:
max(MyDictionary.keys(), key=type).
Retrieve max value:
max(MyDictionary.values(), key=type)
Replace type with the key type in both cases. i.e int
Hope it helps.

Resources