在list-python中找到-1s,1s和0s的多数票

alv*_*vas 9 python binary if-statement voting list

如何找到包含-1s,1s和0s的列表的多数票?

例如,给出一个列表:

x = [-1, -1, -1, -1, 0]
Run Code Online (Sandbox Code Playgroud)

大多数是-1,因此输出应该返回 -1

另一个例子,给出一个列表:

x = [1, 1, 1, 0, 0, -1]
Run Code Online (Sandbox Code Playgroud)

多数票将是 1

当我们有平局时,多数投票应该返回0,例如:

x = [1, 1, 1, -1, -1, -1]
Run Code Online (Sandbox Code Playgroud)

这也应该返回零:

x = [1, 1, 0, 0, -1, -1]
Run Code Online (Sandbox Code Playgroud)

获得多数投票的最简单案例似乎是将列表加起来并检查它是否为负数,正数或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
Run Code Online (Sandbox Code Playgroud)

总结之后,我可以做这个检查以获得多数投票,即:

>>> 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
Run Code Online (Sandbox Code Playgroud)

但如前所述,它很难看:Python将if-elif-else语句放在一行而不是pythonic.

所以解决方案似乎是

>>> x = [-1, -1, 1, 1, 0]
>>> if sum(x) == 0:
...     majority = 0
... else:
...     majority = -1 if sum(x) < 0 else 1
... 
>>> majority
0
Run Code Online (Sandbox Code Playgroud)

EDITED

但有些情况是sum()行不通的,@ RobertB就是这样

>>> x = [-1, -1, 0, 0, 0, 0]
>>> sum(x) 
-2
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,多数票应为0 !!

Rob*_*rtB 10

我假设0票作为票数.所以sum不是一个合理的选择.

尝试一个柜台:

>>> 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
Run Code Online (Sandbox Code Playgroud)

所以你可以编写如下代码:

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'
Run Code Online (Sandbox Code Playgroud)


Pad*_*ham 5

如果使用python> = 3.4,可以使用 statistics.modeStatisticsError,当没有唯一模式时捕获for:

from statistics import mode, StatisticsError

def majority(l):
    try:
        return mode(l)
    except StatisticsError:
        return 0
Run Code Online (Sandbox Code Playgroud)

统计实现本身使用计数器字典:

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')
Run Code Online (Sandbox Code Playgroud)

另一种使用Counter并捕获空列表的方法:

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]
Run Code Online (Sandbox Code Playgroud)