2015-12-29 32 views
2

我想下面的字符串转换:分割字符串到各种数据类型

s = '1|2|a|b' 

[1, 2, 'a', 'b'] 

是否有可能进行转换的一个行?

+0

什么更复杂的数据类型?你期望有多少种数据类型?你有尝试过什么吗?你的代码有什么特定的问题?你为什么试图在一行中做到这一点? – vaultah

+0

@vaultah起初,只是'int'和'string',但我正在考虑如何使用'float'的解决方案。 – wannik

回答

10

是否可以在一行中进行转换?

,这是可能的。但是如何?

算法的方法

  • 拆分使用str.split字符串成其组成部分。这个输出是

    >>> s = '1|2|a|b' 
    >>> s.split('|') 
    ['1', '2', 'a', 'b'] 
    
  • 现在我们已经有一半的问题。接下来,我们需要遍历拆分字符串,然后检查它们每个是字符串还是int。为此,我们使用

  • 列表理解可以很容易地写成[i for i in s.split('|')]。但是,我们如何在那里添加if子句?这包括在One-line list comprehension: if-else variants。现在我们知道哪些元素是int哪些不是,我们可以很容易地调用内置的int

    因此,最终的代码看起来像

    [int(i) if i.isdigit() else i for i in s.split('|')] 
    

现在一个小演示,

>>> s = '1|2|a|b' 
>>> [int(i) if i.isdigit() else i for i in s.split('|')] 
[1, 2, 'a', 'b'] 

正如我们所看到的,输出为预期。


请注意,如果要转换的类型很多,则此方法不适用。

4

你不能做到这一点对负数或大量混合类型的一个线,但你可以使用使用ast.literal_eval功能,将多种类型的工作:

from ast import literal_eval 
def f(s, delim): 
    for ele in s.split(delim): 
     try: 
      yield literal_eval(ele) 
     except ValueError: 
      yield ele 

s = '1|-2|a|b|3.4' 

print(list(f(s,"|"))) 
[1, -2, 'a', 'b', 3.4] 
+0

谢谢你建议'ast.literal_eval'。这非常有用。我现在可以使用两行代码转换为多种类型:'from ast import literal_eval'和'[literal_eval(e)if e [-1] .isdigit()else e for s in s.split('|')]' – wannik

+0

@wannik不用担心,如果你想要一条线,你可以尝试 'list(map(literal_eval,re.sub('(?!\ |)([A-Za-z] +)',''“+ r “\ 1”+“'”,s).split(“|”))))',用引号将字符包裹起来,但功能方法更稳健 –

1

这是可以做到任意多的或复杂如果允许使用帮助功能,则可以在一行中“转换”。 Python本身并不具有“将此字符串转换为它应该表示的类型”的功能,因为它“应该”代表的含义很模糊,并可能因应用程序而异。

def convert(input): 
    converters = [int, float, json.loads] 
    for converter in converters: 
     try: 
      return converter(input) 
     except (TypeError, ValueError): 
      pass 
    # here we assume if all converters failed, it's just a string 
    return input 

s = "1|2.3|a|[4,5]" 
result = [convert(x) for x in s.split("|")] 
+0

这只是pythonic – Netwave

+0

也许你可以建议改进它,然后呢?我不确定它的哪部分对你太过分了。 – GrandOpener

+0

不要冒犯,但在我看来,一堆尝试除外并不是一个好习惯。 – Netwave

1

另一种方法,是使用map内置的方法:

>>> s='1|2|a|b' 
>>> l = map(lambda x: int(x) if x.isdigit() else x, s.split('|')) 
>>> l 
[1, 2, 'a', 'b'] 

如果Python3的话:

>>> s='1|2|a|b' 
>>> l = list(map(lambda x: int(x) if x.isdigit() else x, s.split('|'))) 
>>> l 
[1, 2, 'a', 'b'] 

由于Python3 map会给发电机,所以你必须转换它到list

+0

你真的不需要map-lambda在这里。 –

1

如果你有各种各样的d ata类型(比str和int更多),我相信这可以完成这项工作。

s = '1|2|a|b|[1, 2, 3]|(1, 2, 3)' 
print [eval(x) if not x.isalpha() else x for x in s.split("|")] 

# [1, 2, 'a', 'b', [1, 2, 3], (1, 2, 3)] 

这将失败,如果存在元素,如“B1”