Search code examples
pythonlistif-statementbinaryvoting

Finding majority votes on -1s, 1s and 0s in list - python


How to find the majority votes for a list that can contain -1s, 1s and 0s?

For example, given a list of:

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

The majority is -1 , so the output should return -1

Another example, given a list of:

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

The majority vote would be 1

And when we have a tie, the majority vote should return 0, e.g.:

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

This should also return zero:

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

The simplest case to get the majority vote seem to sum the list up and check whether it's negative, positive or 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

After the sum, I could do this check to get the majority vote, i.e.:

>>> 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

But as noted previously, it's ugly: Python putting an if-elif-else statement on one line and not pythonic.

So the solution seems to be

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

EDITED

But there are cases that sum() won't work, @RobertB's e.g.

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

But in this case the majority vote should be 0!!


Solution

  • I am assuming that votes for 0 count as votes. So sum is not a reasonable option.

    Try a Counter:

    >>> 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
    

    So you could write code like:

    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'