Borda的位置排名

时间:2015-05-15 11:32:41

标签: python algorithm list python-2.7

我有按降序排序的元素树列表。我需要做的是使用Borda’s positional ranking来组合排名列表,使用每个列表中元素的序数等级的信息。给每个候选c和列表ti列出t1,t2,t3 ... tk,得分B ti(c)是在ti中排在c以下的候选者的数量。 所以Borda总分为B(c)=ΣBti(c) 然后候选人按降序Borda分数排序。

我把它捆绑了,但它没有提供所需的输出:

for i in list1, list2, list3:
   borda = (((len(list1)-1) - list1.index(i)) + ((len(list2)-1) - list2.index(i)) + ((len(list3)-1) - list3.index(i)))
   print borda

有人可以帮我实现上述功能吗?

2 个答案:

答案 0 :(得分:1)

调用索引(i)需要与列表大小成比例的时间,并且因为你必须为每个元素调用它,所以它最终需要O(N ^ 2)时间,其中N是列表大小。最好在你知道索引的时候迭代一个列表,并将得分的那一部分添加到dict中的得分累加器。

def borda_sort(lists):
    scores = {}
    for l in lists:
        for idx, elem in enumerate(reversed(l)):
            if not elem in scores:
                scores[elem] = 0
            scores[elem] += idx
    return sorted(scores.keys(), key=lambda elem: scores[elem], reverse=True)

lists = [ ['a', 'c'], ['b', 'd', 'a'], ['b', 'a', 'c', 'd'] ]
print borda_sort(lists)
# ['b', 'a', 'c', 'd']

这里唯一棘手的部分是反向扫描列表;这可以确保如果一个元素根本不在其中一个列表中,那么该列表的分数会增加0。

与其他建议比较:

import itertools
import random

def borda_simple_sort(lists):
    candidates = set(itertools.chain(*lists))
    return sorted([sum([len(l) - l.index(c) - 1 for l in lists if c in l], 0) for c in candidates], reverse=True)
    # returns scores - a bit more work needed to return a list

# make 10 random lists of size 10000
lists = [ random.sample(range(10000), 10000) for x in range(10) ] 
%timeit borda_sort(lists)
10 loops, best of 3: 40.9 ms per loop

%timeit borda_simple_sort(lists)
1 loops, best of 3: 30.8 s per loop

这不是一个错字:) 40 milli 秒对30秒,750x加速。在这种情况下,快速算法读取起来并不困难,甚至可能更容易阅读,它只依赖于适当的辅助数据结构,并以正确的顺序遍历数据。

答案 1 :(得分:0)

这可行:

sorted([sum([len(l) - l.index(c) - 1 for l in [list1, list2, list3] if c in l], 0) for c in [candidate1, candidate2, candidate3]], reverse=True)

请注意,由于分数会重新排序,因此您将忘记每个分数属于哪个候选人:

>>> list1 = ['a', 'c']
>>> list2 = ['b', 'd', 'a']
>>> list3 = ['b', 'a', 'c', 'd']
>>> candidates = ['a', 'b', 'c', 'd']
>>> sorted([sum([len(l) - l.index(c) - 1 for l in [list1, list2, list3] if c in l], 0) for c in candidates], reverse=True)
[5, 3, 1, 1]

在这种情况下,列表的第一个元素(获胜者)是'b',是候选人列表中的第二个元素。