簡體   English   中英

如何將列表中的整數僅拆分為個位數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM