Domanda

Recentemente ho raccolto, tramite un questionario, una serie di pareri su l'importanza dei vari componenti software. Immaginando che una qualche forma di sistema di votazione Condorcet sarebbe il modo migliore per ottenere un punteggio complessivo, ho scelto di utilizzare OpenSTV di analizzarlo.


I miei dati sono in formato tabulare, spazio delimitato, e gli sguardi più o meno come:

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 questo formato, il numero indica il rango e l'ordine della sequenza indica il candidato. Ogni "candidato" ha un rango (richiesto) 1-7, dove un 1 significa più importanti e un 7 mezzi meno importante. Non sono consentiti i duplicati.

Questo formato mi ha colpito come il modo più naturale per rappresentare l'uscita, essendo una rappresentazione diretta del formato scheda elettorale.


Il formato OpenSTV / BLT utilizza un metodo diverso di rappresentare le stesse informazioni, concettualmente come segue:

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

Il formato di file effettivo numerico utilizza il (1-based) indice del candidato, piuttosto che l'etichetta, e così è più simile a:

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

In questo formato, il numero indica il candidato, e l'ordine di sequenza indica il rango . Il reale, formato effettivo BLT include anche un peso che porta e un seguito pari a zero per indicare la fine di ogni votazione, che non mi interessa troppo di questo.


La mia domanda è, qual è il modo più elegante per convertire dal primo formato al (numerico) secondo?

È stato utile?

Soluzione

Ecco la mia soluzione in Python, e funziona bene, ma si sente un po 'goffo. Sono sicuro che c'è un modo più pulito (forse in un'altra lingua?)

Questo mi ha portato più a lungo di quello che dovrebbe avere per avvolgere la mia testa intorno nel pomeriggio di ieri, quindi forse qualcun altro può utilizzare anche questo.

Data:

ballot = '5 2 4 3 7 6 1'

Python una (ish) -liner per convertirlo:

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

In alternativa, in una forma un po 'più comprensibile:

# 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)])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top