【问题标题】:convert string to dict using list comprehension使用列表理解将字符串转换为 dict
【发布时间】:2010-11-17 19:14:32
【问题描述】:

我遇到过几次这个问题,但似乎无法找到一个简单的解决方案。 说我有一个字符串

string = "a=0 b=1 c=3"

我想将其转换为字典,其中 a、b 和 c 为键,0、1 和 3 为它们各自的值(转换为 int)。显然我可以这样做:

list = string.split()
dic = {}
for entry in list:
    key, val = entry.split('=')
    dic[key] = int(val)

但我不太喜欢那个 for 循环,它看起来很简单,你应该能够将它转换为某种列表理解表达式。这适用于 val 可以是字符串的稍微简单的情况。

dic = dict([entry.split('=') for entry in list])

但是,我需要即时将 val 转换为 int,这样的操作在语法上是不正确的。

dic = dict([[entry[0], int(entry[1])] for entry.split('=') in list])

所以我的问题是:有没有办法使用列表理解来消除 for 循环?如果没有,是否有一些内置的 python 方法可以为我做到这一点?

【问题讨论】:

  • 注意:不要使用内置函数作为变量名(stringlist等)

标签: python string dictionary list-comprehension generator-expression


【解决方案1】:

现在您可能应该使用 2.7 中引入的字典理解:

mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())}

字典理解更快、更闪亮(而且,在我看来,更具可读性)。

from timeit import timeit

setup = """mystring = "a=0 b=1 c=3\""""
code1 = """mydict = dict((n,int(v)) for n,v in (a.split('=') for a in mystring.split()))""" # S.Lott's code
code2 = """mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())}"""

print timeit(code1, setup=setup, number=10000) # 0.115524053574
print timeit(code2, setup=setup, number=10000) # 0.105328798294

【讨论】:

    【解决方案2】:

    尝试下一个:

    dict([x.split('=') for x in s.split()])
    

    【讨论】:

    • OP 希望将列表的第二个元素转换为整数。
    【解决方案3】:

    我会这样做:

    def kv(e): return (e[0], int(e[1]))
    d = dict([kv(e.split("=")) for e in string.split(" ")])
    

    【讨论】:

      【解决方案4】:

      我有时喜欢这种方法,尤其是在制作键和值的逻辑比较复杂的时候:

      s = "a=0 b=1 c=3"
      
      def get_key_val(x):
          a,b = x.split('=')
          return a,int(b)
      
      ans = dict(map(get_key_val,s.split()))
      

      【讨论】:

        【解决方案5】:

        没有列表理解的单行如何?

         foo="a=0 b=1 c=3"
         ans=eval( 'dict(%s)'%foo.replace(' ',',')) )
         print ans
        {'a': 0, 'c': 3, 'b': 1}
        

        【讨论】:

        • foo.replace() 将“a=0 b=1 c=3”变成“a=0,b=1,c=3”。字符串格式化创建一个新字符串“dict(a=0,b=1,c=3)”。评估该字符串会产生所需的字典。
        【解决方案6】:

        我喜欢 S.Lott 的解决方案,但我想出了另一种可能性。
        由于您已经有一个类似于您编写方式的字符串,您可以将其调整为 python 语法,然后 eval() 它:)

        import re
        string = "a=0 b=1 c=3"
        string2 = "{"+ re.sub('( |^)(?P<id>\w+)=(?P<val>\d+)', ' "\g<id>":\g<val>,', string) +"}"
        dict = eval(string2)
        print type(string), type(string2), type(dict)
        print string, string2, dict
        

        这里的正则表达式非常原始,不会捕获所有可能的 python 标识符,但为了简单起见,我想保持简单。 当然,如果您可以控制输入字符串的生成方式,只需根据 python 语法生成它并评估它即可。 但是当然你应该执行额外的完整性检查以确保没有代码被注入那里!

        【讨论】:

        • 您想保持简单吗?不要刻薄或挑剔任何人,但这简单在哪里?
        【解决方案7】:
        from cgi import parse_qsl
        text = "a=0 b=1 c=3"
        dic = dict((k, int(v)) for k, v in parse_qsl(text.replace(' ', '&')))
        print dic
        

        打印

        {'a': 0, 'c': 3, 'b': 1}
        

        【讨论】:

          【解决方案8】:

          你是这个意思吗?

          >>> dict( (n,int(v)) for n,v in (a.split('=') for a in string.split() ) )
          {'a': 0, 'c': 3, 'b': 1}
          

          【讨论】:

          • 虽然这很酷,但从长期代码维护的角度来看,我认为我更喜欢原始问题中的版本。原题中的代码一目了然,上面需要几十秒才能理解。
          • @Bryan Oakley:我同意。这个问题(“有没有办法使用列表理解消除 for 循环”)有一个答案。然而,答案可能不是他们真正想要的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-30
          • 2019-03-27
          • 1970-01-01
          • 1970-01-01
          • 2017-06-27
          相关资源
          最近更新 更多