[英]How do a split integers within a list into single digits only?
假设我有这样的事情:
list(range(9:12))
这给了我一个清单:
[9,10,11]
但是我希望它像:
[9,1,0,1,1]
哪一个将每个整数都拆分为个位数,在不牺牲性能的前提下有没有实现这一目标的方法? 还是有一种首先生成此类列表的方法?
最简单的方法是
>>> [int(i) for i in range(9,12) for i in str(i)]
[9, 1, 0, 1, 1]
>>>
您可以有效地构建最终结果,而不必使用itertools.chain.from_iterable
构建一个大和/或小的中间字符串。
In [18]: list(map(int, chain.from_iterable(map(str, range(9, 12)))))
Out[18]: [9, 1, 0, 1, 1]
In [12]: %%timeit
...: list(map(int, chain.from_iterable(map(str, range(9, 20)))))
...:
100000 loops, best of 3: 8.19 µs per loop
In [13]: %%timeit
...: [int(i) for i in ''.join(map(str, range(9, 20)))]
...:
100000 loops, best of 3: 9.15 µs per loop
In [14]: %%timeit
...: [int(x) for i in range(9, 20) for x in str(i)]
...:
100000 loops, best of 3: 9.92 µs per loop
时间随输入而变化。 itertools版本还可以有效地使用内存,尽管与list(map(int, ...))
一起使用时,它比str.join
版本要慢一些:
In [15]: %%timeit
...: list(map(int, chain.from_iterable(map(str, range(9, 200)))))
...:
10000 loops, best of 3: 138 µs per loop
In [16]: %%timeit
...: [int(i) for i in ''.join(map(str, range(9, 200)))]
...:
10000 loops, best of 3: 159 µs per loop
In [17]: %%timeit
...: [int(x) for i in range(9, 200) for x in str(i)]
...:
10000 loops, best of 3: 182 µs per loop
In [18]: %%timeit
...: list(map(int, ''.join(map(str, range(9, 200)))))
...:
10000 loops, best of 3: 130 µs per loop
将整数转换为字符串,然后对字符串进行split()
并将数字重新转换回ints。
li = range(9,12)
digitlist = [int(d) for number in li for d in str(number)]
输出:
[9,1,0,1,1]
我研究了如何使表现更出色。 我编写的第一个函数是naive_single_digits
,它使用str
方法,并且具有相当高效的列表理解功能。
def naive_single_digits(l):
return [int(c) for n in l
for c in str(n)]
如您所见,此方法有效:
In [2]: naive_single_digits(range(9, 15))
Out[2]: [9, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4]
但是,我认为始终为列表中的每个项目构建一个str
对象肯定是不必要的-我们实际需要的只是对数字的基本转换。 出于懒惰,我从这里复制了此函数。 我将其指定为10以优化它。
def base10(n):
if n == 0:
return [0]
digits = []
while n:
digits.append(n % 10)
n //= 10
return digits[::-1]
使用这个,我做了
def arithmetic_single_digits(l):
return [i for n in l
for i in base10(n)]
这也可以正常运行:
In [3]: arithmetic_single_digits(range(9, 15))
Out[3]: [9, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4]
现在要定时了。 我还针对另一个答案进行了测试(完整披露:我对其进行了一些修改以在Python2中工作,但这对性能没有太大影响)
In [11]: %timeit -n 10 naive_single_digits(range(100000))
10 loops, best of 3: 173 ms per loop
In [10]: %timeit -n 10 list(map(int, itertools.chain(*map(str, range(100000)))))
10 loops, best of 3: 154 ms per loop
In [12]: %timeit arithmetic_single_digits(range(100000))
10 loops, best of 3: 93.3 ms per loop
如您所见, arithmetic_single_digits
数实际上更快一些,尽管这是以增加代码和降低清晰度为代价的。 我已经对大量输入进行了测试,因此您可以看到性能上的差异-在任何合理的规模下,这里的每个答案都将非常快。 注意,python的整数算术实际上可能相对较慢,因为它不使用原始整数类型。 如果要在C中实现,我怀疑我的方法会更快一些。
使用(纯)Python 3将其与viblo的答案进行比较(令我感到羞耻的是,我尚未为python 3安装ipython):
print(timeit.timeit("digits(range(1, 100000))", number=10, globals=globals()))
print(timeit.timeit("arithmetic_single_digits(range(1, 100000))", number=10, globals=globals()))
其输出为:
3.5284318959747907
0.806847038998967
我的方法要快得多,大概是因为我纯粹是在使用整数算法。
编写算术解的另一种方法。 与Izaak van Dongens解决方案相比,此解决方案不使用while循环,而是预先计算列表理解/循环中需要多少次迭代。
import itertools, math
def digits(ns):
return list(itertools.chain.from_iterable(
[
[
(abs(n) - (abs(n) // 10 **x)*10**x ) // 10**(x-1)
for x
in range(1+math.floor(math.log10(abs(n) if n!=0 else 1)), 0, -1)]
for n in ns
]
))
digits([-11,-10,-9,0,9,10,11])
将其转换为字符串,然后返回列表:)
lambda x: list(''.join(str(e) for e in x))
您也可以使用地图功能
a=range(9,12)
res = []
b=[map(int, str(i)) for i in a]
for i in b:
res.extend(i)
print(res)
这是我的做法:
ls = range(9,12)
lsNew = []
length = len(ls)
for i in range(length):
item = ls[i]
string = str(item)
if len(string) > 1:
split = list(string)
lsNew = lsNew + split
else:
lsNew.append(item)
ls = lsNew
print(ls)
def breakall(L):
if L == []:
return []
elif L[0] < 10:
return [L[0]] + breakall(L[1:])
else:
return breakall([L[0]//10]) + [L[0] % 10] + breakall(L[1:])
print(breakall([9,10,12]))
-->
[9, 1, 0, 1, 2]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.