1

区切られた文字列を別の場所の辞書でキー:値のペアに分割する方法を見つけましたが、辞書自体に相当する 2 つのパラメーターも含む着信文字列があります: 内部に 1 つまたは 3 つのキー:値のペアを持つパラメーター:

clientid=b59694bf-c7c1-4a3a-8cd5-6dad69f4abb0&keyid=987654321&userdata=ip:192.168.10.10,deviceid:1234,optdata:75BCD15&md=AMT-Cam:avatar&playbackmode=st&ver=6&sessionid=&mk=PC&junketid=1342177342&version=6.7.8.9012

明らかに、これらはプロプライエタリ コードを難読化するためのダミー パラメータです。userdatamdキーの値が辞書自体である辞書に、これらすべてをダンプしたいと思います。

requestdict {'clientid' : 'b59694bf-c7c1-4a3a-8cd5-6dad69f4abb0', 'keyid' : '987654321', 'userdata' : {'ip' : '192.168.10.10', 'deviceid' : '1234', 'optdata' : '75BCD15'}, 'md' : {'Cam' : 'avatar'}, 'playbackmode' : 'st', 'ver' : '6', 'sessionid' : '', 'mk' : 'PC', 'junketid' : '1342177342', 'version' : '6.7.8.9012'}

私が見つけた洗練された 2 レベル区切りの解析コマンドを使用できますか。

requestDict = dict(line.split('=') for line in clientRequest.split('&'))

2 番目のレベルの辞書を処理および保存するために、3 番目のレベルを追加しますか? 構文はどうなりますか?&そうでない場合は、分割してから、含まれている分割をチェックして処理する必要があると思いますが:、それでも構文がわかりません。誰か助けてくれませんか?ありがとう!

4

3 に答える 3

2

私は基本的にカイルの答えを取り、それをより将来に適したものにしました:

def dictelem(input):   
    parts   = input.split('&')
    listing = [part.split('=') for part in parts]

    result = {}
    for entry in listing:
        head, tail = entry[0], ''.join(entry[1:])
        if ':' in tail:
            entries = tail.split(',')
            result.update({ head : dict(e.split(':') for e in entries) })
        else:
            result.update({head: tail})

    return result
于 2012-12-06T22:51:01.097 に答える
1

これが私があなたが望むと思うことをする2つのライナーです:

dictelem = lambda x: x if ':' not in x[1] else [x[0],dict(y.split(':') for y in x[1].split(','))]
a = dict(dictelem(x.split('=')) for x in input.split('&'))
于 2012-12-06T22:14:55.033 に答える
1

私が見つけた洗練された 2 レベル区切りの解析コマンドを使用できますか。

requestDict = dict(line.split('=') for line in clientRequest.split('&'))

2 番目のレベルの辞書を処理および保存するために、3 番目のレベルを追加しますか?

もちろんできますが、(a) 2 レベルを超えるネストされた内包表記は判読不能になる傾向があるため、おそらくそうしたくないでしょう。(b) この非常に単純な構文は、あなたのようなケースでは機能しません。データはdictに変換できます。

たとえば、どうすればよい'PC'でしょうか? それを にし{'PC': None}ますか? それともset {'PC'}?それともlist ['PC']?それともそのまま放置?決定し、そのためのロジックを作成する必要があります。それを式として記述しようとすると、決定が非常に読みにくくなります。

それでは、そのロジックを別の関数に入れましょう。

def parseCommasAndColons(s):
    bits = [bit.split(':') for bit in s.split(',')]
    try:
        return dict(bits)
    except ValueError:
        return bits

これは、コンマで区切られた各コンポーネントの中にコロンがある場合はlikedictを返しますが、そうでない場合はlikeを返します。{'ip': '192.168.10.10', 'deviceid': '1234', 'optdata': '75BCD15'}{'AMT-Cam': 'avatar'}list['1342177342']

これでも少し巧妙すぎるかもしれません。リストのリストを変換して何が起こるかを確認するだけでなく、「これは辞書形式ですか」チェックをより明確にするかもしれません。

いずれにせよ、それを元の理解に戻すにはどうすればよいでしょうか。

さて、あなたはそれを の値で呼び出したいと思いますline.split('=')。そのための関数を追加しましょう。

def parseCommasAndColonsForValue(keyvalue):
    if len(keyvalue) == 2:
        return keyvalue[0], parseCommasAndColons(keyvalue[1])
    else:
        return keyvalue

requestDict = dict(parseCommasAndColonsForValue(line.split('=')) 
                   for line in clientRequest.split('&'))

最後に 1 つ: 古いバージョンの Python で実行する必要がない限りdict、ジェネレータ式を頻繁に呼び出すべきではありません。辞書内包表記で書き直せればほぼ間違いなくその方がわかりやすいし、辞書内包表記で書き換えられないならそもそも一行表記じゃないはず。

もちろん、式を個別の式に分割し、それらの一部をステートメントまたは関数に変換し、それらに名前を付けると、コードが長くなりますが、それは必ずしも悪いことを意味するわけではありません。Zen of Python ( import this) の約半分は、その理由の説明に費やされています。または、Guido からの引用の 1 つ:「Python は、意図的に、コード ゴルフには適していない言語です。」

実際にどのようになるかを知りたい場合は、2 つのステップに分けてみましょう。

>>> {k: [bit2.split(':') for bit2 in v.split(',')] for k, v in (bit.split('=') for bit in s.split('&'))}
{'clientid': [['b59694bf-c7c1-4a3a-8cd5-6dad69f4abb0']],
 'junketid': [['1342177342']],
 'keyid': [['987654321']],
 'md': [['AMT-Cam', 'avatar']],
 'mk': [['PC']],
 'playbackmode': [['st']],
 'sessionid': [['']],
 'userdata': [['ip', '192.168.10.10'],
              ['deviceid', '1234'],
              ['optdata', '75BCD15']],
 'ver': [['6']],
 'version': [['6.7.8.9012']]}

これは、内部レベルの呼び出しを追加できない理由を示していますdict。これらのほとんどは、コロンがないため、実際には辞書ではないからです。それを変更すると、次のようになります。

{k: dict(bit2.split(':') for bit2 in v.split(',')) for k, v in (bit.split('=') for bit in s.split('&'))}

私はそれがあまり読みやすいとは思いませんし、ほとんどの Python プログラマーがそうするとは思えません。今から6か月後にそれを読んで、私が何を意味するのかを理解しようとすると、それを書くよりもはるかに多くの努力が必要になります.

そして、それをデバッグしようとしても楽しくありません。コロンがない入力でそれを実行するとどうなりますか? ValueError: dictionary update sequence element #0 has length 1; 2 is required. どのシーケンス?わかりません。何が機能しないかを確認するには、段階的に分解する必要があります。それは面白くない。

したがって、うまくいけば、これを行いたくない理由が示されます。

于 2012-12-06T21:57:40.913 に答える