引き続きPythonデータ構造。
入れ子のリスト内包
入れ子のリスト内包を説明するために転置行列が使われていてわかりやすい。
このあたりがデータ処理用言語である所以な気がする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
matrix = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ] # 全行を出力 for i in range(4): for x in matrix: print(x) [1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] # 全行のi列目をリスト化 for i in range(4): v = [row[i] for row in matrix] print(v) [1, 5, 9] [2, 6, 10] [3, 7, 11] [4, 8, 12] # 同じことをワンライナーで v = [[row[i] for row in matrix] for i in range(4)] print(v) [1, 5, 9] [2, 6, 10] [3, 7, 11] [4, 8, 12] |
リストの要素削除
del文で要素を削除する。
1 2 3 4 5 6 7 8 |
a = [1,2,3,4,5] del a[3] print(a) [1, 2, 3, 5] del a[:] print(a) [] |
タプル
似て非なるデータ構造リストとタプル。リストは変更可能。タプルは変更不能。
タプルの要素として変更可能な変数を含めることはできる。
作り方が特殊。要素をカンマ区切りで並べるとタプルができる。
要素が1個の場合は、他の変数と区別が付かないので末尾にカンマを配置する。
要素が0個の場合は、()とする。
1 2 3 4 5 6 7 8 9 10 11 |
empty = () print(empty) () tupple = 100,200,300 print(tupple) (100, 200, 300) onetupple = 100, print(onetupple) (100,) |
集合
データ分析用言語なのでこういうのは豊富。順序無し、重複無しのデータを格納する。
重複データを加えるときに重複が除去される。
1 2 3 4 5 6 7 |
hoge = {'hoge1','hoge2','hoge3','hoge4'} print(hoge) set(['hoge4', 'hoge1', 'hoge2', 'hoge3']) fuga = {'fuga1','fuga1','fuga1'} print(fuga) set(['fuga1']) |
リスト内包と同じ書き方で集合内包を記述できる。
1 2 |
v = {x for x in 'abcdefg' if x not in 'abc'} set(['e', 'd', 'g', 'f']) |
ディクショナリ
連想配列。key-valueを格納する。
初期化の方法が複数あるので流してみる。
1 2 3 4 5 6 7 |
dic = dict([('hoge',100),('fuga',500),('hogehog',1000),('fugafuga',2000)]) print(dic) {'fugafuga': 2000, 'fuga': 500, 'hogehog': 1000, 'hoge': 100} dic2 = dict(hoge=100, fuga=500, hogehgoe=1000, fugafuga=2000) print(dic2) {'fugafuga': 2000, 'fuga': 500, 'hogehgoe': 1000, 'hoge': 100} |
ループ内でディクショナリのKeyValueを一度に取る方法を試してみる。
1 2 3 4 5 6 |
for k,v in dic.items(): print(k,v) ('fuga', 500) ('hogehog', 1000) ('hoge', 100) |
ちなみに、普通のリストは先頭から0,1,2,…. のように順序数が振られているはずで、
それを取得するにはenumerate()関数を使う。ループ外で変数を確保してループ内でインクリメントしたりしない。
1 2 3 4 5 |
l = ['hoge','fuga','hogehoge','fugafuga'] (0, 'hoge') (1, 'fuga') (2, 'hogehoge') (3, 'fugafuga') |
2つ以上のシーケンスにループをかけるとき普通はn重ループを書くと思うけれども、
Pythonはzip()関数とアンパッキングを使って1行で書くことができる。
これは良くみるし、Pythonのキモである気がする。
1 2 3 4 5 6 7 8 9 |
qq = ['aaa1', 'bbb1','ccc1','ddd1'] rr = [100, 200, 300, 400] for q, r in zip(qq,rr): print('The value of qq is {0}. The value of rr is {1}'.format(q,r)) The value of qq is aaa1. The value of rr is 100 The value of qq is bbb1. The value of rr is 200 The value of qq is ccc1. The value of rr is 300 The value of qq is ddd1. The value of rr is 400 |
逆順,ソート後ループ
正順のシーケンスにreversed()関数をかますと非破壊で逆順ソートできる。
それをループに使うと逆順ループができる。
sorted()関数をかますと非破壊でシーケンスをソートできる。
それをループに使うとソート後ループができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
n = [1,2,3,4,5,6] for i in reversed(n): print(i) 6 5 4 3 2 1 r = ['alpha','beta','gamma','omega','epsilon'] for i in sorted(r): print(i) alpha beta epsilon gamma omega |
演算子の優先順位
比較演算子は全て同じ優先順位。以下は左から順に比較が行われる。
まずa
不思議な感じだけれども、これにより以下の比較がワンライナーでできる。
1 2 |
a > 1 and a <3 1 < a < 3 |
ブール演算子は比較演算子よりも優先順位が低い。 and,orの優先順位は同じ。notはand,orより高い。以下は同じ。
1 2 |
A and not B or C (A and (not B)) or C |
ブール演算は左から順番に評価され、途中で結論が確定したときに評価は中断される。 Cと異なり、式の途中で代入することはできない。つまり以下みたいなことはできない。
1 |
if a=10<20: |
シーケンスの比較
同じシーケンス型の変数を比較できる。辞書順で要素を比較していき全てが同じであれば真を返す。
両者が異なっていれば、異なっていた箇所の要素の辞書順の大小を返す。
いずれかが片方のサブセットである場合、短い方が小、長い方が大となる。