Finding majority votes on -1s, 1s and 0s in list - python
如何找到包含-1s、1s和0s的列表的多数票?
例如,给出了以下列表:
1 | x = [-1, -1, -1, -1, 0] |
多数是-1,所以输出应该返回
另一个例子是:
1 | x = [1, 1, 1, 0, 0, -1] |
多数票将是
当我们平局时,多数票应返回0,例如:
1 | x = [1, 1, 1, -1, -1, -1] |
这也应返回零:
1 | x = [1, 1, 0, 0, -1, -1] |
最简单的获得多数票的情况似乎是总结名单,检查它是消极的,积极的还是0。
1 2 3 4 5 6 7 8 9 | >>> 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 |
合计后,我可以做这个检查,以获得多数票,即:
1 2 3 4 5 6 7 8 | >>> 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 |
但正如前面提到的,它是丑陋的:Python将if-elif-else语句放在一行上,而不是放在pythonic上。
所以解决办法似乎是
1 2 3 4 5 6 7 8 | >>> x = [-1, -1, 1, 1, 0] >>> if sum(x) == 0: ... majority = 0 ... else: ... majority = -1 if sum(x) < 0 else 1 ... >>> majority 0 |
编辑
但也有一些情况是,
1 2 3 | >>> x = [-1, -1, 0, 0, 0, 0] >>> sum(x) -2 |
但在这种情况下,多数票应该是0!!
我假设0票的票算作票。因此,
试试柜台:
1 2 3 4 5 6 7 8 | >>> 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 |
因此,您可以编写如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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' |
如果使用python>=3.4,则可以使用statistics.mode,在没有唯一模式时捕获
1 2 3 4 5 6 7 | from statistics import mode, StatisticsError def majority(l): try: return mode(l) except StatisticsError: return 0 |
统计信息实现本身使用计数器dict:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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') |
另一种使用计数器并捕获空列表的方法:
1 2 3 | 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] |
此解决方案基于计数发生次数和排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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() |
此外,还有一个if语句。正如评论中提到的,它没有定义发生了什么
x = [1, 1, 0, 0, -1]
您可以计算0的出现次数,并测试它们是否占多数。
1 2 3 4 5 6 7 | >>> 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 |
一个显而易见的方法是制作一个计数器并根据数据列表
1 2 3 4 5 6 7 8 | 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 |
一种非常简单的方法。
1 2 3 4 5 6 7 8 9 10 11 | 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 |
在上面的示例中,输出将为-1,但是,如果有领带,两个钥匙都将被打印出来。
这适用于任何数量的候选人。如果两个候选人之间有平局,则返回零,否则返回多数选票的候选人。
1 2 3 4 5 6 7 | 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] |
我们只比较两个候选,因为如果两个候选之间有一个平局,它应该返回0,并且不依赖于第三个候选值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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) |
我相信这适用于所有提供的测试用例。如果我做错了请告诉我。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
1 2 3 4 5 | from collections import Counter result = Counter(votes).most_common(2) result = 0 if result[0][1] == result[1][1] else result[0][0] |
空的
1 2 3 4 5 6 7 8 9 | 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] |
除了内置的列表操作符和东西之外,您不需要任何东西,也不需要导入任何东西。
1 2 3 4 5 6 7 8 9 10 | 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 |
3d行将各个投票的计数放入一个新的列表中,counts.index()显示我们找到最大投票的列表位置。
我敢说,这应该是尽可能的Python,而不是进入挖眼的一行。
upd:重写不带文本字符串的内容,如果有几个结果相等,则更新为返回0(在原始日志中没有注意到),如果只有一个投票,则添加一个if for case,例如votes=[-1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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])) |