2009-08-10 15 views
67

Ricevo un ditt da uno "strato" di codice su cui vengono eseguiti alcuni calcoli/modifiche prima di passarlo su un altro "livello". I tasti & della stringa originale & sono unicode, ma il livello su cui vengono passati solo accetta str.Il modo più veloce per convertire chiavi e valori di dict da `unicode` a` str`?

Questo sta per essere chiamato spesso, quindi mi piacerebbe sapere che cosa sarebbe il modo più veloce per convertire qualcosa di simile:

{ u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } } 

... a:

{ 'spam': 'eggs', 'foo': True, 'bar': { 'baz': 97 } } 

. ... tenendo presente che i valori non "stringa" devono rimanere come il loro tipo originale.

Qualche idea?

risposta

133
DATA = { u'spam': u'eggs', u'foo': frozenset([u'Gah!']), u'bar': { u'baz': 97 }, 
     u'list': [u'list', (True, u'Maybe'), set([u'and', u'a', u'set', 1])]} 

def convert(data): 
    if isinstance(data, basestring): 
     return str(data) 
    elif isinstance(data, collections.Mapping): 
     return dict(map(convert, data.iteritems())) 
    elif isinstance(data, collections.Iterable): 
     return type(data)(map(convert, data)) 
    else: 
     return data 

print DATA 
print convert(DATA) 
# Prints: 
# {u'list': [u'list', (True, u'Maybe'), set([u'and', u'a', u'set', 1])], u'foo': frozenset([u'Gah!']), u'bar': {u'baz': 97}, u'spam': u'eggs'} 
# {'bar': {'baz': 97}, 'foo': frozenset(['Gah!']), 'list': ['list', (True, 'Maybe'), set(['and', 'a', 'set', 1])], 'spam': 'eggs'} 

Ipotesi:

  • aver importato il modulo di collezioni e può fare uso di classi base astratte che fornisce
  • sei felice per convertire utilizzando la codifica di default (utilizzare data.encode('utf-8') piuttosto di str(data) se è necessaria una codifica esplicita).

Se è necessario supportare altri tipi di contenitori, si spera che sia ovvio come seguire il modello e aggiungere casi per loro.

+0

E cosa si farebbe se alcuni valori fossero elenchi/insiemi/ecc.? –

+0

@Philip: aggiungi casi per loro. Rispondi aggiornato e quindi aggiornato di nuovo per i contenitori di nidificazione all'interno dei contenitori. – RichieHindle

+1

hai dimenticato tuple e frozenset, Richi – SilentGhost

3
def to_str(key, value): 
    if isinstance(key, unicode): 
     key = str(key) 
    if isinstance(value, unicode): 
     value = str(value) 
    return key, value 

passare la chiave e il valore ad esso e aggiungere la ricorsione al codice per tenere conto del dizionario interno.

12

Se si voleva fare questo in linea e non ha bisogno di discesa ricorsiva, questo potrebbe funzionare:

DATA = { u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } } 
print DATA 
# "{ u'spam': u'eggs', u'foo': True, u'bar': { u'baz': 97 } }" 

STRING_DATA = dict([(str(k), v) for k, v in data.items()]) 
print STRING_DATA 
# "{ 'spam': 'eggs', 'foo': True, 'bar': { u'baz': 97 } }" 
+4

Per 2.7 e oltre questo può essere semplificato come segue : '{str (chiave): valore per chiave, valore in data.items()}' – AnjoMan

19

Lo so, sono in ritardo su questo:

def convert_keys_to_string(dictionary): 
    """Recursively converts dictionary keys to strings.""" 
    if not isinstance(dictionary, dict): 
     return dictionary 
    return dict((str(k), convert_keys_to_string(v)) 
     for k, v in dictionary.items()) 
+1

Sì, questo sembra il modo corretto di farlo, le versioni in linea e altre non sono davvero sufficienti per gli scenari del mondo reale. male non c'è un modo affidabile inline senza ricorrere a questo, o forse c'è basato su python str (...) convenzioni json? – jayunit100

+1

Questo è il mio preferito, per convertire solo le chiavi, che è quello che stavo cercando. : è necessario un ulteriore() intorno all'argomento dict() restituito. – ggll

+0

grazie man. Tutto buono e funzionante. Cheers !! – ashim888

2

per un non dict -nested (dal momento che il titolo non menziona questo caso, potrebbe essere interessante per altre persone)

{str(k): str(v) for k, v in my_dict.items()} 
+1

{str (k): str (v) per k, v in my_dict.items()} –

2

per rendere il tutto inlin e (non ricorsivo):

{str(k):(str(v) if isinstance(v, unicode) else v) for k,v in my_dict.items()} 
Problemi correlati