Frage

Ich habe kürzlich einen Fragebogen verwendet, eine Reihe von Meinungen zur Bedeutung verschiedener Softwarekomponenten. Da ich feststellte, dass irgendeine Form der Condorcet -Abstimmungsmethode der beste Weg ist, um einen Gesamtrang zu erhalten, entschied ich mich, Openstv zu verwenden, um ihn zu analysieren.


Meine Daten sind im tabellarischen Format, der Platz abgenommen und sieht mehr oder weniger aus wie:

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

In diesem Format gibt die Zahl den Rang an und die Sequenzreihenfolge zeigt den Kandidaten an.Jeder "Kandidat" hat einen Rang (erforderlich) von 1 bis 7, wobei ein 1 das wichtigste und 7 bedeutet, das am wenigsten wichtig ist. Keine Duplikate sind erlaubt.

Dieses Format war mir die natürlichste Art, die Ausgabe darzustellen, da es sich um eine direkte Darstellung des Stimmzettelsformats handelte.


Das OpenStV/BLT -Format verwendet eine andere Methode, um dieselben Informationen konzeptionell wie folgt darzustellen:

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

Das tatsächliche numerische Dateiformat verwendet den (1-basierten) Index des Kandidaten und nicht das Etikett, und ist daher eher:

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

In diesem Format gibt die Zahl den Kandidaten an, und die Sequenzreihenfolge zeigt den Rang an. Das tatsächliche, reale BLT -Format enthält auch ein führendes Gewicht und eine folgende Null, um das Ende jedes Stimmzettels anzuzeigen, was mir dafür nicht zu viel wichtig ist.


Meine Frage ist, Was ist der eleganteste Weg, um vom ersten Format in den (numerischen) zweiten zu konvertieren?

War es hilfreich?

Lösung

Hier ist meine Lösung in Python und es funktioniert in Ordnung, fühlt sich aber ein wenig ungeschickt an. Ich bin sicher, es gibt einen saubereren Weg (vielleicht in einer anderen Sprache?)

Dies dauerte länger, als es gestern Nachmittag um den Kopf wickeln musste, also kann es vielleicht auch jemand anderes benutzen.

Gegeben:

ballot = '5 2 4 3 7 6 1'

Python One (ish) -Liner, um es zu konvertieren:

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

Alternativ in einer etwas verständlicheren Form:

# 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)])
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top