python list if-statement binary voting

Encontrar votos de la mayoría en-1, 1 y 0 en la lista-Python



if-statement binary (13)

# These are your actual votes votes = [-1, -1, -1, -1, 0] # These are the options on the ballot ballot = (-1, 0, 1) # This is to initialize your counters counters = {x: 0 for x in ballot} # Count the number of votes for vote in votes: counters[vote] += 1 results = counters.values().sort() if len(set(values)) < len(ballot) and values[-1] == values [-2]: # Return 0 if there''s a tie return 0 else: # Return your winning vote if there isn''t a tie return max(counters, key=counters.get)

¿Cómo encontrar la mayoría de los votos para una lista que puede contener -1s, 1s y 0s?

Por ejemplo, dada una lista de:

x = [-1, -1, -1, -1, 0]

La mayoría es -1, por lo que la salida debería devolver -1

Otro ejemplo, dada una lista de:

x = [1, 1, 1, 0, 0, -1]

El voto mayoritario sería 1

Y cuando tenemos un empate, el voto de la mayoría debe devolver 0, por ejemplo:

x = [1, 1, 1, -1, -1, -1]

Esto también debería devolver cero:

x = [1, 1, 0, 0, -1, -1]

El caso más simple para obtener el voto mayoritario parece resumir la lista y verificar si es negativa, positiva o 0.

>>> x = [-1, -1, -1, -1, 0] >>> sum(x) # So majority -> 0 -4 >>> x = [-1, 1, 1, 1, 0] >>> sum(x) # So majority -> 1 2 >>> x = [-1, -1, 1, 1, 0] >>> sum(x) # So majority is tied, i.e. -> 0 0

Después de la suma, podría hacer este control para obtener la mayoría de votos, es decir:

>>> x = [-1, 1, 1, 1, 0] >>> majority = -1 if sum(x) < 0 else 1 if sum(x)!=0 else 0 >>> majority 1 >>> x = [-1, -1, 1, 1, 0] >>> majority = -1 if sum(x) < 0 else 1 if sum(x)!=0 else 0 >>> majority 0

Pero como se señaló anteriormente, es feo: Python coloca una declaración if-elif-else en una línea y no en pythonic.

Entonces la solución parece ser

>>> x = [-1, -1, 1, 1, 0] >>> if sum(x) == 0: ... majority = 0 ... else: ... majority = -1 if sum(x) < 0 else 1 ... >>> majority 0

EDITADO

Pero hay casos en que sum() no funcionará, @ RobertB, por ejemplo

>>> x = [-1, -1, 0, 0, 0, 0] >>> sum(x) -2

¡Pero en este caso el voto de la mayoría debería ser 0!


Creo que esto funciona para todos los casos de prueba proporcionados. Por favor, avíseme si hice algo mal.

from collections import Counter def fn(x): counts = Counter(x) num_n1 = counts.get(-1, 0) num_p1 = counts.get(1, 0) num_z = counts.get(0, 0) if num_n1 > num_p1: return -1 if num_n1 > num_z else 0 elif num_p1 > num_n1: return 1 if num_p1 > num_z else 0 else: return 0


Supongo que los votos para 0 cuentan como votos. Entonces la sum no es una opción razonable.

Pruebe un contador:

>>> from collections import Counter >>> x = Counter([-1,-1,-1, 1,1,1,1,0,0,0,0,0,0,0,0]) >>> x Counter({0: 8, 1: 4, -1: 3}) >>> x.most_common(1) [(0, 8)] >>> x.most_common(1)[0][0] 0

Entonces podrías escribir código como:

from collections import Counter def find_majority(votes): vote_count = Counter(votes) top_two = vote_count.most_common(2) if len(top_two)>1 and top_two[0][1] == top_two[1][1]: # It is a tie return 0 return top_two[0][0] >>> find_majority([1,1,-1,-1,0]) # It is a tie 0 >>> find_majority([1,1,1,1, -1,-1,-1,0]) 1 >>> find_majority([-1,-1,0,0,0]) # Votes for zero win 0 >>> find_majority([''a'',''a'',''b'',]) # Totally not asked for, but would work ''a''


from collections import Counter result = Counter(votes).most_common(2) result = 0 if result[0][1] == result[1][1] else result[0][0]

El manejo de errores para listas de votes vacías o listas de votes con una cardinalidad establecida de 1 es trivial y se deja como ejercicio para el lector.


import numpy as np def fn(vote): n=vote[np.where(vote<0)].size p=vote[np.where(vote>0)].size ret=np.sign(p-n) z=vote.size-p-n if z>=max(p,n): ret=0 return ret # some test cases print fn(np.array([-1,-1, 1,1,1,1,0,0,0,0,0,0,0,0])) print fn(np.array([-1, -1, -1, 1,1,1,0,0])) print fn(np.array([0,0,0,1,1,1])) print fn(np.array([1,1,1,1, -1,-1,-1,0])) print fn(np.array([-1, -1, -1, -1, 1, 0]))


Esta solución se basa en el conteo de las ocurrencias y la clasificación:

import operator def determineMajority(x): '''''' >>> determineMajority([-1, -1, -1, -1, 0]) -1 >>> determineMajority([1, 1, 1, 0, 0, -1]) 1 >>> determineMajority([1, 1, 1, -1, -1, -1]) 0 >>> determineMajority([1, 1, 1, 0, 0, 0]) 0 >>> determineMajority([1, 1, 0, 0, -1, -1]) 0 >>> determineMajority([-1, -1, 0, 0, 0, 0]) 0 '''''' # Count three times # sort on counts xs = sorted( [(i, x.count(i)) for i in range(-1,2)], key=operator.itemgetter(1), reverse=True ) if xs[0][1] > xs[1][1]: return xs[0][0] else: # tie return 0 if __name__ == ''__main__'': import doctest doctest.testmod()

Además, hay una si las declaraciones. Como se mencionó en los comentarios, no está definido qué sucede con

x = [1, 1, 0, 0, -1]


No necesita nada más que los operadores de listas incorporadas y esas cosas, no es necesario importar nada.

votes = [ -1,-1,0,1,0,1,-1,-1] # note that we don''t care about ordering counts = [ votes.count(-1),votes.count(0),votes.count(1)] if (counts[0]>0 and counts.count(counts[0]) > 1) or (counts[1]>0 and counts.count(counts[1])>1): majority=0 else: majority=counts.index(max(counts))-1 # subtract 1 as indexes start with 0 print majority

La línea 3d pone los conteos de los votos respectivos en una nueva lista, y counts.index () nos muestra en qué posición de la lista encontramos los votos máximos.

Me atrevería a decir que esto debería ser lo más pitónico posible, sin meterse en espeluznantes especuladores.

Upd: reescribió sin cadenas de texto y se actualizó para devolver 0 en caso de varios resultados iguales (no se notó esto en la publicación original), se agregó una IF para el caso si solo un voto, por ejemplo votos = [- 1]


Puede usar statistics.mode si estaba usando python> = 3.4, capturando un StatisticsError para cuando no tiene un modo único:

from statistics import mode, StatisticsError def majority(l): try: return mode(l) except StatisticsError: return 0

La implementación de las estadísticas en sí misma usa un Contador Dict:

import collections def _counts(data): # Generate a table of sorted (value, frequency) pairs. table = collections.Counter(iter(data)).most_common() if not table: return table # Extract the values with the highest frequency. maxfreq = table[0][1] for i in range(1, len(table)): if table[i][1] != maxfreq: table = table[:i] break return table def mode(data): """Return the most common data point from discrete or nominal data. ``mode`` assumes discrete data, and returns a single value. This is the standard treatment of the mode as commonly taught in schools: >>> mode([1, 1, 2, 3, 3, 3, 3, 4]) 3 This also works with nominal (non-numeric) data: >>> mode(["red", "blue", "blue", "red", "green", "red", "red"]) ''red'' If there is not exactly one most common value, ``mode`` will raise StatisticsError. """ # Generate a table of sorted (value, frequency) pairs. table = _counts(data) if len(table) == 1: return table[0][0] elif table: raise StatisticsError( ''no unique mode; found %d equally common values'' % len(table) ) else: raise StatisticsError(''no mode for empty data'')

Otra forma de usar un contador y atrapar una lista vacía:

def majority(l): cn = Counter(l).most_common(2) return 0 if len(cn) > 1 and cn[0][1] == cn[1][1] else next(iter(cn),[0])[0]


from collections import Counter def find_majority_vote(votes): counter = Counter(votes) most_common = counter.most_common(2) if len(most_common)==2: return 0 if most_common[0][1] == most_common[1][1] else most_common[0][0] else: return most_common[0][0]


Esto funciona con cualquier número de candidatos. Si hay un empate entre dos candidatos, devuelve cero, de lo contrario, devuelve el candidato con la mayoría de los votos.

from collections import Counter x = [-1, -1, 0, 0, 0, 0] counts = list((Counter(x).most_common())) ## Array in descending order by votes if len(counts)>1 and (counts[0][1] == counts[1][1]): ## Comparing top two candidates print 0 else: print counts[0][0]

Comparamos solo dos candidatos porque si hay un empate entre dos candidatos debería devolver 0 y no depende del tercer valor candidato


Un enfoque muy simple.

a = [-1, -1, -1, -1, 0] # Example count = {} for i in a: if i not in count: count[i] = 1 else: count[i] += 1 m_count = max(count.values()) for key in count: if count[key] == m_count: print key

En el ejemplo anterior, la salida será -1, sin embargo, si hay un empate, ambas claves se imprimirán.


Un enfoque obvio es hacer un contador y actualizarlo de acuerdo con la lista de datos x . Luego puede obtener la lista de números (de -1, 0, 1) que son los más frecuentes. Si hay 1 de esos números, esto es lo que desea, de lo contrario, elija 0 (como lo solicitó).

counter = {-1: 0, 0: 0, 1: 0} for number in x: counter[number] += 1 best_values = [i for i in (-1, 0, 1) if counter[i] == max(counter.values())] if len(best_values) == 1: majority = best_values[0] else: majority = 0


Puede contar las ocurrencias de 0 y probar si son mayoría.

>>> x = [1, 1, 0, 0, 0] >>> if sum(x) == 0 or x.count(0) >= len(x) / 2.0: ... majority = 0 ... else: ... majority = -1 if (sum(x) < 0) else 1 ... majority 0