2017-08-22 59 views
0

比方說,我有這樣的事情:如何將列表內的整數分割爲單個數字?

list(range(9:12)) 

,給了我一個清單:

[9,10,11] 

不過,我希望它是這樣的:

[9,1,0,1,1] 

其中每個整數分成個位數,有沒有實現這一點,而不犧牲太多的表現?或者有沒有一種方法來生成這樣的列表呢?

回答

4

您可以高效地構建最終結果,而無需使用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 
0

把它轉化爲一個字符串,然後再返回到一個列表:)

lambda x: list(''.join(str(e) for e in x)) 
3

轉換整數爲字符串,然後split()字符串並重新轉換數字回整數。

li = range(9,12) 

digitlist = [int(d) for number in li for d in str(number)] 

輸出:

[9,1,0,1,1] 
4

最簡單的方法是,

>>> [int(i) for i in range(9,12) for i in str(i)] 
[9, 1, 0, 1, 1] 
>>> 
0

你也可以做地圖功能

a=range(9,12) 
res = [] 
b=[map(int, str(i)) for i in a] 
for i in b: 
    res.extend(i) 

print(res) 
0

這裏是我是如何做的:

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) 
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對象列表中的每個項目 - 所有我們實際需要是一個基數轉換爲數字。出於懶惰,我從here複製了此功能。我已經通過將其指定爲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語言實現的,我會懷疑我的方法會更快一些。

比較這viblo的答案,使用(純)Python 3中(我的恥辱,我還沒有安裝IPython中爲Python 3):

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 

我的方法比較快,大概是因爲我純粹使用整數算術。

1

編寫算術解決方案的另一種方法。與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]) 
+0

真棒:D.你是一個勇敢的人,比我進入這樣的算法的膽量。順便說一下,對於數字([0]),你會得到一個數學域錯誤,儘管0確實有數字。 –

+0

謝謝,我更新了處理0和負整數的代碼。不幸的是,與其他解決方案相比,它的速度非常緩慢。 – viblo

0
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] 
相關問題