最近,我收集了有关各种软件组件的重要性的一系列意见。我认为某种形式的condorcet投票方法将是获得整体排名的最佳方法,我选择使用OpenStv进行分析。


我的数据采用表格格式,空间界定,看起来或多或少如下:

A B C D E F G    # Candidates
5 2 4 3 7 6 1    # First ballot. G is ranked first, and E is ranked 7th
4 2 6 5 1 7 3    # Second ballot
etc

以这种格式,数字表示等级,序列顺序表示候选。每个“候选人”的等级(要求)从1到7,其中1表示最重要,而7表示最不重要。不允许重复。

这种格式使我成为表示输出的最自然方式,是投票格式的直接表示。


OpenSTV/BLT格式使用不同的表示相同信息的方法,从概念上如下:

G B D C A F E    # Again, G is ranked first and E is ranked 7th
E B G A D C F    # 
etc

实际的数字文件格式使用候选人的(1个基于1)索引,而不是标签,因此更像是:

7 2 4 3 1 6 5    # Same ballots as before.
5 2 7 1 4 3 6    # A -> 1, G -> 7

以这种格式,数字指示候选人,序列顺序表示等级. 。实际的,真实的BLT格式还包括指导重量和以下零,以指示每个选票的结尾,我对此并不过分关心。


我的问题是, 从第一个格式转换为(数字)第二的最优雅的方式是什么?

有帮助吗?

解决方案

这是我在Python中的解决方案,效果还不错,但感觉有些笨拙。我确定有一种更干净的方式(也许是另一种语言?)

这花了我比昨天下午在我的头上要花的时间更长,所以也许其他人也可以使用它。

给定:

ballot = '5 2 4 3 7 6 1'

python One(ISH)-Liner转换它:

rank = [i for r,i in sorted((int(r),i+1) for i,r in enumerate(ballot.split())]
rank = " ".join(rank)

或者,以更容易理解的形式:

# Split into a list and convert to integers
int_ballot = [int(x) for x in ballot.split()]

# This is the important bit.
# enumerate(int_ballot) yields pairs of (zero-based-candidate-index, rank)
# Use a list comprehension to swap to (rank, one-based-candidate-index)
ranked_ballot = [(rank,index+1) for index,rank in enumerate(int_ballot)]

# Sort by the ranking. Python sorts tuples in lexicographic order
# (ie sorts on first element)
# Use a comprehension to extract the candidate from each pair
rank = " ".join([candidate for rank,candidate in sorted(ranked_ballot)])
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top