あなたの入力が引用符やエスケープを行わないと仮定できる場合(あなたの例はそうではありませんが、それは必ずしもそれが良い仮定であることを意味するわけではありません)、コンマで区切られた複数のキーを持つことはできず、複数の値だけを持つことはできません(それ以外の場合、形式があいまいになるため、これはおそらく適切な仮定です...):
まず、中かっこを削除してから、コロンで分割します。
>>> A = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}"
>>> A[1:-1].split(':')
['user_id', '34dd833,category', 'secondary,items', 'camera,vcr,dvd,type', 'sg_ser']
したがって、最初のエントリは最初のキーで、最後のエントリは最後の値であり、その間のすべてのエントリは N 番目の値の後にコンマが続き、その後に N+1 番目のキーが続きます。そこには他のコンマがあるかもしれませんが、最後のコンマは常に N+1 番目のキーから N 番目の値を分割します。(そして、これは N=0 でも機能します。コンマがないため、最後のコンマは 0 番目のキーから何も分割しません。しかし、残念ながら、最後のエントリでは機能しません。これについては後で説明します。)
これを簡潔にする方法はいくつかありますが、最初にコードとして明示的に記述して、その仕組みを理解できるようにしましょう。
>>> d = {}
>>> entries = A[1:-1].split(':')
>>> for i in range(len(entries)-1):
... key = entries[i].rpartition(',')[-1]
... value = entries[i+1].rpartition(',')[0]
... d[key] = value
これはほぼ正しいです:
>>> d
{'category': 'secondary', 'items': 'camera,vcr,dvd', 'type': '', 'user_id': '34dd833'}
上記のように、最後のものには機能しません。その理由は明らかです。そうでない場合はrpartition(',')
、最後の値に対して何が返されるかを確認してください。,
手動でパッチを適用するか、最後に余分なものを詰め込んでごまかすことができます( entries = (A[1:-1] + ',').split(':')
)。しかし、考えてみると、rsplit
の代わりにrpartition
,[0]
が正しいことを行います。では、代わりにそうしましょう。
では、これを少しきれいにするにはどうすればよいでしょうか。
entries
まず、隣接するペアのリストに変換しましょう。ここで、各ペアのそれぞれ(n, nplus1)
がn.rpartition(',')[-1]
キーでありnplus1.rsplit(',', 1)[0]
、対応する値です。そう:
>>> A = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}"
>>> entries = A[1:-1].split(':')
>>> adjpairs = zip(entries, entries[1:])
>>> d = {k.rpartition(',')[-1]: v.rsplit(',', 1)[0] for k, v in adjpairs}