web-dev-qa-db-ja.com

複数の整数のリストを単一の整数に変換する方法は?

Python 3.5などのリストを次のように変換するにはどうすればよいですか。

x=[1, 3, 5]

135のint(整数)に?

15

intsのリストがあり、それらを結合したい場合は、 mapstr を使用できます。それらを文字列に変換するには、空の文字列をjoinに変換し、次に int を使用してintsにキャストバックします。

コードでは、これは次のようになります。

r = int("".join(map(str, x)))

そしてr135の必要な値が含まれるようになりました。

もちろん、これはいくつかの条件に伴う限定的なアプローチです。問題のリストには、正のints(サンプルとして)またはintsを表す文字列のみが含まれている必要があります。それ以外の場合、文字列への変換ステップは失敗するか、(負の)数値の結合になります。不格好になります。

これは、前後に文字列に変換する必要がないより数学的な方法です。 0 <= i <= 9の場合にのみ機能することに注意してください。

>>> x = [1, 3, 5]
>>> sum(d * 10**i for i, d in enumerate(x[::-1]))
135

アイデアは、リスト内の各要素に対応する10の累乗を乗算し、結果を合計することです。

30
brianpck

数式のみを使用して(文字列への変換を行わない)、reduce関数(functools.reduce in Python 3)

b = reduce(lambda total, d: 10*total + d, x, 0)

これは、乗算の数を減らすために数を表す多項式を因数分解するホーナーの法則を利用します。例えば、

1357 = 1*10*10*10 + 3*10*10 + 5*10 + 7     # 6 multiplications
     = ((1*10 + 3)*10 + 5)*10 + 7          # 3 multiplications

その結果、これは10の累乗を計算したり、文字列を作成して結果を整数に変換したりするよりも高速です。

>>> timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', 'from functools import reduce; x=[1,3,5,7]')
0.7217515400843695
>>> timeit.timeit('int("".join(map(str, [1,3,5,7])))')
1.425914661027491
>>> timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', 'x=[1,3,5,7]')
1.897974518011324

公平に言えば、桁数が大きくなると文字列変換はより高速になります。

>>> import timeit

# 30 digits
>>> setup='from functools import reduce; x=[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]' 
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
6.520374411018565
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
6.797425839002244
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
19.430233853985555

# 60 digits
>>> setup='from functools import reduce; x=2*[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]' 
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
13.648188541992567
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
12.864593736943789
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
44.141602706047706

# 120 digits!
>>> setup='from functools import reduce; x=4*[5, 2, 6, 8, 4, 6, 6, 4, 8, 0, 3, 1, 7, 6, 8, 2, 9, 9, 9, 5, 4, 5, 5, 4, 3, 6, 9, 2, 2, 1]' 
>>> print(timeit.timeit('reduce(lambda t,d: 10*t+d, x, 0)', setup))
28.364255172084086
>>> print(timeit.timeit('int("".join(map(str, x)))', setup))
25.184791765059344
>>> print(timeit.timeit('sum(d * 10**i for i, d in enumerate(x[::-1]))', setup))
99.88558598596137
23
chepner

マップが気に入らない場合は、常にリスト内包表記を使用できます。

s = [str(i) for i in x]
r = int("".join(s))
1
user6774416