To count the frequency of all elements in a list, just use a Counter
. Then, to get the most and least frequent, use the method most_common
:
import random
from collections import Counter
# gera 10 números aleatórios entre 0 e 10
numeros = random.choices(range(11), k=10)
print(f'Os numeros gerados foram: {numeros}')
frequencias = Counter(numeros).most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]
print(f'O número que ocorre mais vezes é {mais_frequente[0]}, ocorrendo {mais_frequente[1]} vezes')
print(f'O número que ocorre menos vezes é {menos_frequente[0]}, ocorrendo {menos_frequente[1]} vezes')
most_common
returns a list of tuples, each tuple containing the element and the respective amount of times it occurs. Thus, the most frequent is the first element of this list, and the least frequent is the last.
The other answers suggest using the method count
list, but this is an inefficient way, because each time count
is called, it runs through the entire list to get the count of a single element. That is, you will be going through the list several times, to get the count of all elements.
Worse, for an element that occurs more than once, you will be getting the count of it several times. This is not only unnecessary, but extremely inefficient - of course for small lists will not make so much difference, but for larger lists, the difference is striking. And it doesn’t even have to be that big: doing a test with a list of 2000 elements, the Counter
was much faster (a few hundred times faster). Increase to 10 thousand elements, the difference becomes even greater.
When you go through a list several times without need, you are creating a variation of the call "Shlemiel the Painter’s Algorithm". The problem is that we often only test with small lists and do not notice the problem, but if you do it in large volumes of data, then it will make all the difference.
So, use a Counter
It is better because you only go through the list once, getting the count of all the elements. But we still have to solve the case of draws, when more than one element is the most (or least) frequent. How most_common
already returns the elements in the order (from most frequent to least frequent), just go through the list from the beginning (or the end) and stop when you find a different count:
frequencias = Counter(numeros).most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]
print(f'Números mais frequentes (ocorrem {mais_frequente[1]} vezes)')
for f in frequencias:
if f[1] == mais_frequente[1]:
print(f[0])
else:
break
print(f'Números menos frequentes (ocorrem {menos_frequente[1]} vezes)')
for f in reversed(frequencias):
if f[1] == menos_frequente[1]:
print(f[0])
else:
break
Finally, also note that to generate a list of 10 random numbers between 0 and 10, you can use random.choices
, passing by range(11)
, that generates a range
with the numbers between 0 and 10 (since a range
does not include the final value). Remembering that random.choices
is available from Python 3.6. For earlier versions, you can simplify your loop, trading it for a comprehensilist on, much more succinct and pythonic:
# gera 10 números aleatórios entre 0 e 10
numeros = [ random.randint(0, 10) for _ in range(10) ]
You can still optimize more, because if you use the Counter
to get the frequencies, and then use max
and min
to get the largest and smallest element, you will be going through the list 3 times (one for the Counter
, another to max
and another to min
). If you want to do everything in one loop, then you will have to do everything manually (but depending on the size of the list, it may make up for not having to travel it several times):
contagens = Counter()
maior = float('-inf') # infinito negativo
menor = float('inf') # infinito
for n in numeros:
contagens.update([n])
if n > maior:
maior = n
if n < menor:
menor = n
frequencias = contagens.most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]
print(f'Números mais frequentes (ocorrem {mais_frequente[1]} vezes)')
for f in frequencias:
if f[1] == mais_frequente[1]:
print(f[0])
else:
break
print(f'Números menos frequentes (ocorrem {menos_frequente[1]} vezes)')
for f in reversed(frequencias):
if f[1] == menos_frequente[1]:
print(f[0])
else:
break
print(f'O maior número é {maior}')
print(f'O menor número é {menor}')
This loop is a little less efficient than using the Counter
directly, but still, much faster than use set
and/or count
.
Yesterday I answered a similar question. See help: https://answall.com/a/456064/137387
– Augusto Vasques