I'm trying to make a polls app where user will give their input according to available choices
# they can be different also `len` of `choices` list can be changed
choices = ['Agree', 'Disagree', 'Leave Blank']
And the user_input will 1 item from the choices. like
new_user_input = 'Agree' # that could be anything from choices
I've been struggling with returning accurate results with out running multiple iterations.
Lets see what I'm trying :
def find_occurency_percentage(list_):
return {i: round(list_.count(i)/len(list_)*100, 2) for i in list_}
Running this function in Scenario 1:
# Fist Scenario
all_user_inputs = ['Agree', 'Disagree', 'Agree', 'Disagree', 'Agree', ]
new_user_input = 'Agree' # that could be anything from choices
all_user_inputs.append(new_user_input)
print(find_occurency_percentage(all_user_inputs))
'''
current result = {'Agree': 66.67, 'Disagree': 33.33}
expected result = {'Agree' : 66.67, 'Disagree': 33.33, 'Leave Blank' : 00.0}
'''
My problem is I'm unable to handle it so that the result should be according to all original choices
. Not just only all_user_inputs
Here are more examples to understand the problem with running compiler https://godbolt.org/z/eTqYWd54e
CodePudding user response:
This should be more understandable
from collections import Counter
def find_occurency_percentage(list_, choices):
counts = Counter(list_)
return {k: counts[k] / len(list_) for k in choices}
choices = ['Agree', 'Disagree', 'Leave Blank']
all_user_inputs = ['Agree', 'Disagree', 'Agree', 'Disagree', 'Agree', 'Agree']
print(find_occurency_percentage(all_user_inputs, choices))
# {'Agree': 0.6666666666666666, 'Disagree': 0.3333333333333333, 'Leave Blank': 0.0}
CodePudding user response:
Iterate over choices instead:
{choice: round(100 * _list.count(k) / len(_list), 2) for choice in choices}
This has the added benefit of only iterating once over a much smaller input space, choices
, as opposed to a theoretically much larger space, which is the user inputs.