2009-10-10 6 views
3

En Python, j'ai besoin de générer un dict qui mappe une lettre sur une représentation prédéfinie "one-hot" de cette lettre. A titre d'illustration, le dict devrait ressembler à ceci:Génération d'une représentation sous forme de chaîne d'un codage mono-codage

{ 'A': '1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0', 
    'B': '0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0', # ... 
} 

Il y a un bit (représenté comme un caractère) par lettre de l'alphabet. Par conséquent, chaque chaîne contiendra 25 zéros et un 1. La position du 1 est déterminée par la position de la lettre correspondante dans l'alphabet.

je suis venu avec un code qui génère ceci:

# Character set is explicitly specified for fine grained control 
_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
n = len(_letters) 
one_hot = [' '.join(['0']*a + ['1'] + ['0']*b) 
      for a, b in zip(range(n), range(n-1, -1, -1))] 
outputs = dict(zip(_letters, one_hot)) 

est-il un moyen plus efficace/propre/plus pythonique à faire la même chose?

Répondre

7

Je trouve cela plus lisible:

from string import ascii_uppercase 

one_hot = {} 
for i, l in enumerate(ascii_uppercase): 
    bits = ['0']*26; bits[i] = '1' 
    one_hot[l] = ' '.join(bits) 

Si vous avez besoin d'un alphabet plus général, énumérer un peu plus d'une chaîne de caractères, et le remplacer par ['0']*26 .

+0

Très lisible. +1 –

+0

Nice. Je pense que j'ai essayé une tentative laide de programmation fonctionnelle. Votre version est beaucoup plus lisible cependant. –

+0

L'utilisation de 'ascii_uppercase' est une bonne idée (je ne savais même pas qu'il existait.), Mais je ne suis pas sûr que ce soit plus lisible que le code original. La compréhension de la liste est laconique, mais elle est aussi très expressive. L'utilisation d'une boucle explicite rend le but du code moins clair à mes yeux. – bcat

0

Cela semble assez clair, concis, et Pythonic pour moi.

1
one_hot = [' '.join(['0']*a + ['1'] + ['0']*b) 
      for a, b in zip(range(n), range(n-1, -1, -1))] 
outputs = dict(zip(_letters, one_hot)) 

En particulier, il y a beaucoup code emballé dans ces deux lignes. Vous pourriez essayer le refactoring Introduce Explaining Variable. Ou peut-être un extract method.

est ici un exemple:

def single_onehot(a, b): 
    return ' '.join(['0']*a + ['1'] + ['0']*b) 

range_zip = zip(range(n), range(n-1, -1, -1)) 
one_hot = [ single_onehot(a, b) for a, b in range_zip] 
outputs = dict(zip(_letters, one_hot)) 

Bien que vous pourriez être en désaccord avec ma nomination.

2

En Python 2.5 et jusqu'à vous pouvez utiliser l'opérateur conditionnel:

from string import ascii_uppercase 

one_hot = {} 
for i, c in enumerate(ascii_uppercase): 
    one_hot[c] = ' '.join('1' if j == i else '0' for j in range(26)) 
Questions connexes