0

本着短代码的精神......我有一个数字或空字符串列表,我希望map(int, mylist)它不会失败。

mylist = "123//456".split("/") #['123', '', '456']
myints = <something to quickly convert the list>

编辑 我需要保持相同数量的令牌。即myints = [123, 0, 456]

我在想一些类似的东西map(lambda x: int(x) or 0, mylist),但是当然这仍然会抛出一个ValueError. 有任何想法吗?


另一个编辑

一些结果(时间for xrange(1000000))...

  • 2.03s l = map(lambda x: x.isdigit() and int(x) or 0, mylist)
  • 1.37s l = [x.isdigit() and int(x) or 0 for x in mylist]
  • 1.99s l = map(lambda x: int(x) if x.isdigit() else 0, mylist)
  • 1.35s l = [int(x) if x.isdigit() else 0 for x in mylist]
  • 1.24s l = [int(x or 0) for x in mylist]
  • 1.45s l = [int(e) if e.strip() else 0 for e in mylist]
  • 4.44s the big chunk of code with try/except ergo 越大越慢 :) 好的,并非总是如此

只是将这些包括在他们的时间里,因为它们没有产生所需的输出......

  • 3.71s l = map(int, re.findall('[0-9]+', "123//456"))('课程正则表达式很慢。时间和地点)
  • 1.47s l = map(int, filter(None, mylist))
  • 1.15 秒 [int(x) for x in mylist if x](好时机!)

*我应该提到re.compile将 3.71 秒缩短到 2.11 秒。

Python 2.7.3, Xeon E5-1607

myints = [int(x or 0) for x in mylist]不仅速度最快且结果正确,而且非常短,只有 29 个字符。

感谢大家的意见!没有那么多反对者:P

4

8 回答 8

4

简短,虽然不像其他答案那么健壮 -x必须是一个空字符串或一个数字:

[int(x or 0) for x in mylist]
于 2013-11-01T08:31:59.747 回答
2
myints = map(lambda x: int(x) if x.isdigit() else 0, "123//456".split("/")) # returns [123, 0, 456]

如您所愿,它保留相同数量的标记,并用 zeros 替换非数字字符串

编辑:您也可以通过理解来做到这一点:

myints = [int(x) if x.isdigit() else 0 for x in "123//456".split("/")]
于 2013-11-01T07:18:24.223 回答
2

短并不总是最好的,但这很短:

>>> [int(e) if e.strip() else 0 for e in "123//456".split("/")]
[123, 0, 456]

还:

>>> map(int, (e if e.isdigit() else '0' for e in "123//456".split("/")))
于 2013-11-01T07:18:33.613 回答
2

在我看来,这就像for循环比列表理解更具可读性的情况。但是如果你真的想用尽可能少的代码来做,试试这个:

myints = [int(x) if x.isdigit() else 0 for x in mylist]

显然,对于非数字字符串,您可以使用任何您喜欢的值来代替 0,这将包括空字符串。

for循环形式将是这样的:

myints = []
for x in mylist:
    try:
        intx = int(x)
    except (TypeError, ValueError):
        intx = 0
    finally:
        myints.append(intx)

这种形式的优点是可以处理任何int可以处理的输入,负数会跳到脑海中 -'-7'.isidigit()将返回False,因此任何int(x) if x.isdigit() else 0解决方案都将'123//-7'变成[123, 0, 0]而不是[123, 0, -7]. 你的问题陈述没有解决负整数,所以我不确定你需要什么。

于 2013-11-01T07:18:45.500 回答
1

尝试使用列表理解

my_ints = [int(x) for x in my_str.split('/') if x]
于 2013-11-01T07:15:34.833 回答
1

使用regex

>>> import re
>>> map(int, re.findall('[0-9]+', "123//456////1231231"))
[123, 456, 1231231]

如果字符串很大,那么您可以使用re.finditer列表推导:

>>> [int(m.group()) for m in re.finditer('[0-9]+', "123//456////1231231")]
[123, 456, 1231231]

对于您的编辑,您可以使用str.isdigit三元表达式

>>> mylist = "123//456"
>>> [int(x) if x.isdigit() else 0 for x in mylist.split('/')]
[123, 0, 456]
于 2013-11-01T07:16:29.037 回答
0

为什么不分开'//'

print map(int, "123//456".split('//'))

如果这不是一个选项,那么您可以执行以下操作:

print map(int, filter(None, mylist))

或者,如果您想保持相同的长度:

print map(lambda x: int(x) if x.isdigit() else 0, mylist)
于 2013-11-01T07:15:18.427 回答
0

实际上,这是一种可行的方法,但是需要额外调用.isdigit(),这似乎不是必需的。

mylist = "123//456".split("/") #['123', '', '456']
myints = map(lambda x: x.isdigit() and int(x) or 0, mylist)

[123, 0, 456]
于 2013-11-01T07:18:49.310 回答