web-dev-qa-db-ja.com

python 1回の反復で2つの値を生成するリスト内包表記

python次のようにリストを生成したい-

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....]

あなたは考え出したでしょう、それはn, n*n

次のようにpythonでそのようなリスト内包表記を書いてみました-

lst_gen = [i, i*i for i in range(1, 10)]

しかし、これを行うと、構文エラーが発生します。

リスト内包表記を介して上記のリストを生成する良い方法は何でしょうか?

40
user1629366

使用する - itertools.chain.from_iterable

>>> from itertools import chain
>>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]

または、 generator 関数を使用することもできます:

>>> def solve(n):
...     for i in xrange(1,n+1):
...         yield i
...         yield i**2

>>> list(solve(5))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
41

質問は古いですが、好奇心reader盛な読者のために、別の可能性を提案します。最初の投稿で述べたように、数字のリストから簡単にカップル(i、i ** 2)を作成できます。次に、このカップルをフラット化します。したがって、理解に平坦化操作を追加するだけです。

[x for i in range(1, 10) for x in (i,i**2)]
14
Yann

あまり知られていないトリック:リスト内包表記には複数のfor句を含めることができます。

例えば:

>>> [10*x+y for x in range(4) for y in range(3)]
[0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]

あなたの特定のケースでは、次のことができます:

>>> [x*x if y else x for x in range(5) for y in range(2)]
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16]
6
Jonathan Mayer

リスト内包表記は、一度にone要素を生成します。代わりに、一度に1つの値のみを生成するようにループを変更するオプションがあります。

_[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
_

または、タプルを作成し、itertools.chain.from_iterable()を使用してリストをフラット化します。

_from itertools import chain

list(chain.from_iterable((i, i*i) for i in range(1, 10)))
_

出力:

_>>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
>>> list(chain.from_iterable((i, i*i) for i in range(1, 10)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
_
5
Martijn Pieters
lst_gen = sum([(i, i*i) for i in range(1, 10)],())

ああ私は合計がおそらく1つの反復規則を破るに言及する必要があります:(

5
Joran Beasley

リストのリストを作成してから、reduceを使用してそれらを結合できます。

print [[n,n*n] for n in range (10)]

[[0、0]、[1、1]、[2、4]、[3、9]、[4、16]、[5、25]、[6、36]、[7、49]、[ 8、64]、[9、81]]

print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)])

[0、0、1、1、2、4、3、9、4、16、5、25、6、36、7、49、8、64、9、81]

 print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\
 for n in range (1,10)])

[1、1、1、2、4、8、3、9、27、4、16、64、5、25、125、6、36、216、7、49、343、8、64、512、9 、81、729]

Reduceは、2つの引数を取る呼び出し可能な式を取り、最初の2つの項目から開始してシーケンスを処理します。最後の式の結果は、その後の呼び出しの最初の項目として使用されます。この場合、各リストはリストのリストの最初のリストに次々に追加され、そのリストが結果として返されます。

リスト内包表記は、「for var in sequence」式で定義された変数とシーケンスを使用して、ラムダ式で暗黙的にmapを呼び出します。以下は同じようなものです。

map(lambda n:[n,n*n],range(1,10))

[[1、1]、[2、4]、[3、9]、[4、16]、[5、25]、[6、36]、[7、49]、[8、64]、[ 9、81]]

より自然なpython reduceの式については知りません。

3
John Hall

別のオプションは、

>>> from itertools import izip, tee
>>> g = xrange(1, 11)
>>> x, y = tee(g)
>>> y = (i**2 for i in y)
>>> z = izip(x, y)
>>> output = []
>>> for k in z:
...     output.extend(k)
... 
>>> print output
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100]
2
iruvar

別のオプション:

reduce(lambda x,y: x + [y, y*y], range(1,10), [])
1
Matthew Plourde

このスレッドには多くのトリックがあります。インポートなしで1ライナージェネレーターを使用する別の例

x = (lamdba : [[(yield i), (yield i**2)] for i in range(10)])()

編集:これは、Python 3.7でDeprecatedWarningを発生させ、Python 3.8でSyntaxErrorを発生させます: https://docs.python.org/dev/whatsnew /3.7.html#deprecated-python-behavior

1
Hielke Walinga
>>> lst_gen = [[i, i*i] for i in range(1, 10)]
>>> 
>>> lst_gen
[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
>>> 
>>> [num for elem in lst_gen for num in elem]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

ここに私のリファレンスがあります http://docs.python.org/2/tutorial/datastructures.html

1
Supriya K

この2つのライナーを試してみてください

lst = [[i, i*i] for i in range(10)]
[lst.extend(i) for i in lst]

必要に応じて数学を変更します。

より良い

#Change my_range to be the number you want range() function of
start = 1
my_range = 10
lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)]
0
ytpillai

前述のように、 itertools が方法です。ここに私がそれをする方法があります、私はそれをより明確に見つけます:

[i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])]
0
ntg