2012-12-06 28 views
1

我发现如何分割分隔字符串转换键:在字典中elsewhere值对,但我有一个输入字符串,还包括两个参数量字典本身:参数有一个或三个关键:内在价值对:解析字符串三级划分成字典

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

我可以拿我发现光滑两级划界解析命令:

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

,并添加第三级以它来处理&保持2级词典?语法是什么?如果不是,我想我将不得不拆分&,然后检查&句柄拆分包含:但即使如此,我无法弄清楚语法。有人可以帮忙吗?谢谢!

+0

你可能想存储'” sessionid'键为'None'。 – Droogans

回答

2

我基本上采取了Kyle's answer并使其更加面向未来的友好:

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 
+0

非常感谢你们俩。 –

1

我可以拿我发现光滑两级划界解析命令:

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

,并添加第三级以它来处理&保持2级字典?

当然可以,但(a)您可能不想给,因为超过两个级别的嵌套内涵往往会得到不可读,和(b)这个超级简单的语法,不会像情况下工作你的,只有一些数据可以变成字典。

例如,应'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 

这将返回一个dict{'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('&')) 

最后一件事:除非你需要在旧版本的Python运行,你不应该经常上一些发电机表情叫dict。如果它可以被重写为字典理解,那么它几乎肯定会更清晰,如果它不能被重写为字典理解,那么首先它可能不应该是单线程表达式。

当然,将表达式分解成单独的表达式,将其中的一些表达式转换为语句或函数,并命名它们会使代码变长 - 但这并不意味着更糟。大约一半的Python的禅(import this)致力于解释为什么。或者Guido的一句话:“Python是一种糟糕的代码高尔夫语言,故意这样做。”

如果你真的想知道它会是什么样子,让我们打破它分为两个步骤:

>>> {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。哪个序列?不知道。你必须一步一步分解它,看看哪些工作不起作用。这并不好玩。

所以,希望能够说明你为什么不想这样做。

+0

非常感谢设计原理,非常感谢。 –

1

下面是一个双内胆,做什么,我想你想:

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('&')) 
+0

我做了我自己的这个思维弯曲解决方案的版本。 '但是'')''可能不能复制你。 – Droogans

+0

谢谢!是的,对于这样复杂的事情来说,明确一下发生的事情要好得多,而不是试图巧妙地简洁,这是我的一个坏习惯。 –

+0

实际上,现在我读了这个,唯一不可读的是''''参数的oneth元素的索引。一切都看起来很简单,简洁。 – Droogans