Question

Je réunis récemment, à l'aide d'un questionnaire, un ensemble d'opinions sur l'importance des différents composants logiciels. Figuring qu'une certaine forme de méthode de vote Condorcet serait la meilleure façon d'obtenir un classement général, je choisi d'utiliser OpenSTV pour l'analyser.


Mes données est sous forme de tableau, l'espace délimité, et ressemble plus ou moins comme:

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

Dans ce format, le nombre indique le rang et l'ordre de séquence indique le candidat. Chaque « candidat » a un rang (obligatoire) de 1 à 7, où un 1 moyen le plus important et un 7 moyen le moins important. Aucun doublon sont autorisés.

Ce format qui m'a frappé comme la façon la plus naturelle pour représenter la sortie, étant une représentation directe du format de vote.


Le format OpenSTV / BLT utilise une méthode différente de représenter la même information, sur le plan conceptuel que suit:

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

Le format de fichier numérique réelle utilise l'index du candidat (base 1), plutôt que l'étiquette, et est donc plus comme:

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

Dans ce format, le nombre indique le candidat, et l'ordre de séquence indique le rang . Le vrai réel, format de BLT comprend également un important poids et suivant zéro pour indiquer la fin de chaque tour de scrutin, que je ne me soucie pas trop pour cela.


Ma question est, ce qui est la façon la plus élégante pour convertir du premier format à la (numérique) secondes?

Était-ce utile?

La solution

Voici ma solution en Python, et il fonctionne bien, mais se sent un peu maladroit. Je suis sûr qu'il ya un moyen plus propre (peut-être dans une autre langue?)

Cela me prend plus de temps que devrait avoir à envelopper la tête autour de l'après-midi hier, alors peut-être que quelqu'un d'autre peut utiliser aussi.

Vu:

ballot = '5 2 4 3 7 6 1'

python une (ish) -liner pour le convertir:

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

En variante, sous une forme légèrement plus compréhensible:

# 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)])
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top