web-dev-qa-db-fra.com

Le moyen le plus rapide de convertir les clés et les valeurs d'un dict de `unicode` en` str`?

Je reçois un dict d'une "couche" de code sur laquelle des calculs/modifications sont effectués avant de le transmettre à une autre "couche". Les valeurs clés et "chaîne" du dict original sont unicode, mais la couche sur laquelle elles sont transmises est uniquement compatible avec str.

Cela va être appelé souvent, alors j'aimerais savoir quel serait le moyen le plus rapide de convertir quelque chose comme:

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

...à:

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

... en gardant à l'esprit que les valeurs autres que "chaîne" doivent rester dans leur type d'origine.

Des pensées?

77
Phillip B Oldham
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'}

Hypothèses:

  • Vous avez importé le module collections et pouvez utiliser les classes de base abstraites qu'il fournit.
  • Vous êtes heureux de convertir en utilisant l'encodage par défaut (utilisez data.encode('utf-8') plutôt que str(data) si vous avez besoin d'un encodage explicite).

Si vous avez besoin de prendre en charge d’autres types de conteneurs, nous espérons que la façon de suivre le modèle et d’ajouter des cas pour eux est évidente.

147
RichieHindle

Je sais que je suis en retard sur celui-ci:

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())
23
Germano

Si vous voulez faire cela en ligne et que vous n'avez pas besoin de descente récursive, cela pourrait fonctionner:

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 } }"
12
Samuel Clay
def to_str(key, value):
    if isinstance(key, unicode):
        key = str(key)
    if isinstance(value, unicode):
        value = str(value)
    return key, value

transmettez la clé et la valeur, et ajoutez de la récursivité à votre code pour prendre en compte le dictionnaire interne.

3
SilentGhost

pour un dict non imbriqué (puisque le titre ne mentionne pas ce cas, cela pourrait être intéressant pour d'autres personnes)

{str(k): str(v) for k, v in my_dict.items()}
3
maxbellec

Pour que tout soit en ligne (non récursif):

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