LoginSignup
2
5

More than 3 years have passed since last update.

Pythonのリスト内包表記を使って色々やってみよう

Last updated at Posted at 2019-11-08

1.はじめに

 Pythonに関して記事を書くのは初めてですね。最近はnimなるマイナー言語を嗜んでいるのですが、本当にマイナーなのでPythonも並行して勉強しつつ、友人たちに「nimはいいぞ、ジョージ...」とnimを布教する日々を過ごしてます。
 さて話は逸れましたが、今回はPythonのリスト内包表記で色んな問題を解きつつリスト内包表記に慣れていこうかなという記事を書こうかなと思います。

2.リスト内包表記の表現の仕方(ラムダ式とかif文とか)

まずは基本から

全要素が同じ値のリストを作りたい。

a=[0 for i in range(10)]
#[0,0,0,0,0,0,0,0,0,0]

ある規則に則った値を要素に持つリストを作りたい。

例えば交差1の等差数列

a=[i for i in range(10)]
#[0,1,2,3,4,5,6,7,8,9]

関数f(x)を用いて

def f(x):
  return x**2
a=[f(i) for i in range(10)]
#[0,1,4,9,16,25,36,49,64,81]

#あるいはこんな感じでも
b=[i**2 for i in range(10)]
#[0,1,4,9,16,25,36,49,64,81]

ラムダ式を使ってみましょう

a=[(lambda price,tax:price + (price * tax))(100*i,0.08) for i in range(10)]
#[0.0,108.0,216.0,324.0,432.0,540.0,648.0,756.0,864.0,972.0]

if文を使って条件に合った要素だけを持つリストを作りたい。

ifのみを使った場合

a=[i for i in range(10) if i%2==0]
#[0,2,4,6,8]

if-elseを使った場合

a=[x if x%2==1 else 0 for x in range(10)]
#[0,1,0,3,0,5,0,7,0,9]

3.色々な問題を解いてみる

コインの裏表

コインが100枚表を上にして一列に並んでいる。2の倍数番目のを裏返す。3の倍数番目を裏返す。4の倍数番目を裏返す。... ということを順に行なった時に、表になっているコインは何番目のコインか。

#表が1,裏が0
#2番目以上に関しては、約数の数の偶奇によって裏か表か決まる
#例えば2のとき、1回しかひっくり返さない⇒"約数の個数が偶数ならばコインは裏"
[print([k+1 for k,j in enumerate([0 if len([i for i in range(2,int(y/2)+1) if y%i==0])%2==0 
       else 1 for y in range(1,101)]) if j==1])]
#[4, 9, 16, 25, 36, 49, 64, 81, 100]
#これやってみて気づいたけど、x**2で表せる数が答えになるのね...(x**2の約数xが重複するから)

#別解
import math
[print([i**2 for i in range(2,int(math.sqrt(100))+1)])]
#[4, 9, 16, 25, 36, 49, 64, 81, 100]

#ライブラリのimportもできるらしいのでやってみますね
[print([i**2 for i in range(2,int([math.sqrt(100) for math in [__import__('math')]][0])+1)])]
#[4, 9, 16, 25, 36, 49, 64, 81, 100]

いやー頭おかしくなりそう

1000までの完全数

[print([j for j in range(1,1001) if sum([i for i in range(1,int(j/2)+1) if j%i==0])==j])]
#[6,28,496]

何となく乱数からのソート

[print(sorted([int(rd.uniform(0,100)) for rd in [__import__('random')] for i in range(100)]))]

1000までの素数

[print([i for i in range(2,1000) if 0 not in 
       [i%j for j in range(2,int([math.sqrt(i) for math in [__import__('math')]][0])+1)]])]
"""
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 
113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 
251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 
397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 
557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 
701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 
863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
"""

三元一次方程式を解いてみる

たとえば、「500円玉と100円玉と10円玉がそれぞれ40,60,30枚あります。それらを用いて合計が9000円になるようにするにはそれぞれの硬貨を何枚ずつ用いればよいか」みたいな問題の時に使えます。

[ns 
 for ns in [dict()] if not(
        ns.update({"A":40}) or
        ns.update({"B":60}) or
        ns.update({"C":30}) or
        ns.update({"x":9000}) or
        print([[a,b,c] 
        for a in range(A+1) 
        for b in range(B+1) 
        for c in range(C+1) 
        if 500*a+100*b+10*c==x]))]

#[[14, 19, 10], [14, 20, 0], [15, 14, 10], [15, 15, 0], [16, 9, 10], [16, 10, 0], [17, 4, 10], [17, 5, 0], [18, 0, 0]]

2行目の"if not"の部分は"if"でも大丈夫です。[i for i in range(10) if i%2==0]のifと同じく、Trueならリストの要素になるしFalseならならないというものなので、このリスト全体をprintしたときに[{'A':40,'B':60,'C':30,'x':9000}]となるか[]となるかの違いです。

4.最後に

余談ですが(というか私個人の備忘録として)、上のor頻発リストについて書いておきます。
pythonにおいてprint()の真偽値はFalseらしく(以下の通り戻り値はNoneでした。) 、たとえばこんなことができます。

if print(5)==True:
    print("fxxk")
elif print(5)==None:
    print("brain fxxk")
else:
    print("brain")
#brain fxxk

加えてpythonでは、AがTrueのとき"A or B"は自明にTrueなのでBの評価を行いません。(AがFalseのときの"A and B"も同様に)

[print(5) or print(3) and print(4)]
#5
#3
#4はprintされない

また何か新しいことできるようになったら追記しますね。リスト内包表記はチューリング完全らしい...ボソッ

2
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5