如何将列表中的分割整数转换为单个数字?

时间:2017-08-22 10:49:01

标签: python python-3.x list

让我说我有这样的事情:

08-22 12:33:10.833 13362-13362/com.my.blacky E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.my.blacky, PID: 13362
java.lang.ClassCastException: com.my.blacky.PrefsActivity cannot be cast to com.my.blacky.MainActivity
   at com.gerpue.blacky.FragmentPrefs$2.onPreferenceClick(FragmentPrefs.java:62)
   at android.preference.Preference.performClick(Preference.java:996)
   at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:214)
   at android.widget.AdapterView.performItemClick(AdapterView.java:310)
   at android.widget.AbsListView.performItemClick(AbsListView.java:1188)
   at android.widget.AbsListView$PerformClick.run(AbsListView.java:3105)
   at android.widget.AbsListView$3.run(AbsListView.java:4096)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:148)
   at android.app.ActivityThread.main(ActivityThread.java:5551)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

这给了我一个清单:

    list(range(9:12))

但我希望它像:

    [9,10,11]

将每个整数分成单个数字,无论如何在不牺牲太多性能的情况下实现这一目标?或者有没有办法首先生成这样的列表?

9 个答案:

答案 0 :(得分:4)

最简单的方法是,

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

答案 1 :(得分:4)

您可以有效地构建最终结果,而无需使用itertools.chain.from_iterable构建一个大型和/或小型中间字符串。

Sub test()

    Dim wb1 As Excel.Workbook
    Set wb1 = Workbooks("XXX.XLSM")                ' from here, use wb1 to refer to fua.xlsm

    Dim wb2 As Excel.Workbook                      ' ditto for wb2
    Set wb2 = Workbooks.Open("C:\Users\Ha.csv")

    Dim sht1 As Worksheet                          ' ditto for sht1
    Set sht1 = wb1.Sheets("Sheet1")

    Dim sht2 As Worksheet
     Set sht2 = wb2.Sheets("Ha")

    If Application.WorksheetFunction.CountA(sht1.Cells) <> 0 Then

        LastRow = sht1.Cells.Find( _
                        What:="*", _
                        After:=sht1.Range("A1"), _
                        Lookat:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByRows, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).row
    Else
        LastRow = 1
    End If




  sht1.ListObjects.Add(xlSrcRange, sht1.Range("A:I"), xlYes).Name = "Table1"





    sht1.ListObjects("Table1").Range.AutoFilter _
                Field:=9, _
                Criteria1:=">=-1000000000000", _
                Operator:=xlAnd, _
                Criteria2:="<=1000000000000000"

    Application.DisplayAlerts = False          ' not sure if needed



      sht1.Range("A:I").SpecialCells(xlCellTypeVisible).Copy

    On Error Resume Next
   sht2.Range("A:I").Copy Columns(last_col + 1).PasteSpecial
    On Error Resume Next
    Application.DisplayAlerts = True           ' not sure if needed

    wb2.Save                                   ' already C:\Users\Ha.csv
    wb2.Close

End Sub
In [18]: list(map(int, chain.from_iterable(map(str, range(9, 12)))))
Out[18]: [9, 1, 0, 1, 1]

计时与输入相关。 itertools 版本还有效地使用内存,但如果与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 一起使用,它比str.join版本略慢:

list(map(int, ...))

答案 2 :(得分:3)

将整数转换为字符串,然后将split()转换为字符串并将数字重新转换回整数。

li = range(9,12)

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

输出:

[9,1,0,1,1]

答案 3 :(得分: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(令我遗憾的是我还没有为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

我的方法相当快,大概是因为我纯粹使用整数运算。

答案 4 :(得分: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])

答案 5 :(得分:0)

将其转换为字符串然后返回列表:)

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

答案 6 :(得分:0)

您也可以使用地图功能

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

print(res)

答案 7 :(得分: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)

答案 8 :(得分: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]