Pythonデータ構造

リスト

覚えるものでもないのだけれども一度は通しておきたいリストのメソッド。
大方の言語と違って、基本的に破壊的メソッドだらけ。

append()で末尾に追加。



v = []
v.append(10)
v[len(v):] = [30]
print(v)
[10 20]

リストを伸長。


r = [20]
v.extend(r)
print(v)
[10 20 30]

リストに挿入。


v.insert(0,100)
print(v)
[100, 10, 30, 20]

要素の削除。


v.remove(10)
print(v)
[100, 30, 20]

要素のインデックス。indexOf(…)みたいな。
要素が無いと-1を返しそうだけれどもエラー。


idx = v.index(20)
print(idx)
idx2 = v.index(1000)
print(idx2)
ValueError: 1000 is not in list

含まれる要素xの個数を返す不思議なメソッド。


cnt = v.count(20)
print(cnt)

要素を逆順にする。コピーしたものを逆順にするのではなくそのものを逆順にする。


v.reverse()
[20, 30, 100]

コピーする。


vv = v.copy()
vv[0] = 'hoge'
print(v)
print(vv)
[20, 30, 100]
['hoge', 30, 100]

リスト内包

例えば0から9までの値の2乗のリストを作成するコードは以下。


squares = []
for x in range(10):
    squares.append(x**2)

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Pythonっぽくワンライナーで書くとこうなる。

map関数は高階関数。第1引数として関数、第2引数としてシーケンスを取る。
lambdaは関数のSyntaxSugarなので第1引数はlambdaも渡せる。
渡したシーケンスの全要素についてlambda式を実行した結果を返す。

range(10)は0から9まで。lambda x:x**2は引数を2乗する。
なのでmap(lambda x: x**2, range(10))は、0 1,4,9,…を返す。
それをlist()でリスト化する。


squares = list(map(lambda x: x**2, range(10)))
print(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Pythonでは、これが言語仕様で出来るようになっている。リスト内包。
[]の中の最初は式。式に続けてfor式,if式を書ける。


squares2 = [x**2 for x in range(10)]
print(squares2)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

より複雑な式,for式をリスト内包にしてみる。以下は等価。


cs = []
for x in [1,2,3]:
   for y in [3,1,4]:
      if x != y:
          cs.append((x,y))
print(cs)
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

cs2 = [(x,y) for x in [1,2,3] for y in [3,1,4] if x != y]
print(cs2)
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

色々な書き方が出来る。戻り値をタプルにしたい場合は()で囲う必要がある。


vec = [-4, -2, 0 ,2, 4]
cs3 = [x*2 for x in vec]
print(cs3)
[-8, -4, 0, 4, 8]

cs4 = [x for x in vec if x >= 0]
print(cs4)
[0, 2, 4]

cs5 = [(x, x**2) for x in range(10)]
print(cs5)
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)]

以下面白い。リスト内包には入れ子の関数も含められる。


from math import pi
cs6 = [str(round(pi, i)) for i in range(1,6)]
print(cs6)