Преобразование формата ранга на кандидата в формат OpenSTV BLT - PullRequest
1 голос
/ 03 июня 2010

Я недавно собрал, используя анкету, ряд мнений о важности различных программных компонентов. Полагая, что какая-либо форма голосования Кондорсе будет лучшим способом для получения общего ранга, я решил использовать 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), а не метку, и поэтому больше похож на:

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

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


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

1 Ответ

0 голосов
/ 03 июня 2010

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

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

Дано:

ballot = '5 2 4 3 7 6 1'

Python one (ish) -линер для его преобразования:

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)])
...