web-dev-qa-db-ja.com

辞書のキーと値を「unicode」から「str」に変換する最も速い方法は?

別の「レイヤー」に渡す前に、いくつかの計算/変更が実行されるコードの「レイヤー」から辞書を受け取っています。元の辞書のキーと「文字列」値はunicodeですが、それらが渡されるレイヤーはstrのみを受け入れます。

これは頻繁に呼び出されるので、次のようなものを変換する最も速い方法は何かを知りたいです:

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

...に:

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

...非「文字列」値は元の型のままである必要があることに留意してください。

何かご意見は?

77
_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'}
_

仮定:

  • コレクションモジュールをインポートし、それが提供する抽象基本クラスを利用できます
  • デフォルトのエンコードを使用して変換できます(明示的なエンコードが必要な場合は、data.encode('utf-8')ではなくstr(data)を使用してください)。

他の種類のコンテナをサポートする必要がある場合は、パターンに従ってケースを追加する方法が明らかであることを願っています。

147
RichieHindle

私はこれに遅れていることを知っています:

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

これをインラインで行いたい場合で、再帰的な降下を必要としない場合、これはうまくいくかもしれません:

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

キーと値を渡し、コードに再帰を追加して内部辞書を考慮します。

3
SilentGhost

ネストされていない辞書の場合(タイトルにそのケースが記載されていないため、他の人にとっては興味深いかもしれません)

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

すべてインライン(非再帰的)にするには:

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