2010-06-03 15 views
0

Недавно я собрал, используя анкету, набор мнений о важности различных программных компонентов. Полагая, что какой-то метод голосования Condorcet будет лучшим способом получить общий рейтинг, я решил использовать OpenSTV для его анализа.Преобразование формата ранжирования в формат OpenSTV BLT


Мои данные в табличном формате, пространство, ограниченное, и выглядит более или менее как:

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/БЗУ использует другой метод, представляющий ту же информацию, концептуально следующим образом:

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) индекс кандидата, а не ярлык, а так больше похож:

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

В этом формате, число указывает на кандидата, и порядок последовательности указывает на ранг. Фактический, реальный, BLT-формат также включает в себя основной вес и следующий ноль, чтобы указать конец каждого голосования, о котором я не слишком забочусь об этом.


Мой вопрос, , что это самый элегантный способ для преобразования из первого формата в (числовую) секунду?

ответ

0

Вот мое решение в Python, и оно работает нормально, но чувствует себя немного неуклюжим. Я уверен, что есть более чистый способ (возможно, на другом языке?)

Это заняло у меня больше времени, чем должно было обернуться вокруг вчерашнего дня, так что, возможно, кто-то еще может это использовать.

Дано:

ballot = '5 2 4 3 7 6 1' 

Python один (МОГ) -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)]) 
Смежные вопросы