リストのいろいろ
リストのいろんな使い方
tags: | python, tips, experiment, list |
---|---|
created: | 2007-02-05T20:24:24 |
リストのいろんな使い方 Pythonではリスト(配列オブジェクト)が活躍しています。
基本
作成
直接記述によるリスト作成
>>> a = [1,2,3]
>>> a
[1, 2, 3]
一定の連番値を持つリストの作成
>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
一般的な配列とは違う性質として、
>>> [1,'hoge',3]
[1, 'hoge', 3]
このように、違う型の値を持つことができます。
注釈
この特性のために大量のオブジェクトをリストに入れるとそれなりにメモリを 消費してしまいます。同じ型の値を大量に入れたい場合は標準のarrayモジュールか、 numpyモジュールを使いましょう!
参照
インデックス参照
>>> a = range(10)
>>> a[3]
3
0から始まるインデックスで各要素にアクセスできますね。
>>> a = range(10)
>>> a[-1]
9
このように、負のインデックスを指定すると、リストの右から数えた値を参照できます。
スライス
- list_obj[start:end:step]
- start以上end未満をstep単位でスライスすることで部分要素群を取り出せます。
- start
- リストの左からのインデックス値を指定します。 負の数を使うとリストの右からのインデックス値とみなします。 スライス結果にこのインデックス位置の値を含みます。 省略すると、「0」を指定したのと同じ意味になります。
- end
- リストの左からのインデックス値を指定します。 負の数を使うとリストの右からのインデックス値とみなします。 スライス結果にこのインデックス位置の値は含みません。 省略すると、「(リスト要素数)」を指定したのと同じ意味になります。
- step
- 取り出しステップを整数で指定します。 0(zero)はエラーになります。 負の数も使えますが、そのときはstart、endを省略しないといけない。 省略すると、「1」を指定したのと同じ意味になります。
>>> a = range(10)
>>> a[3:]
[3, 4, 5, 6, 7, 8, 9]
こう書くと、インデックス3以降が取り出せます。
以下いろいろ
>>> a = range(10)
>>> a[1:3]
[1, 2]
>>> a[:-2]
[0, 1, 2, 3, 4, 5, 6, 7]
>>> a[-2:]
[8, 9]
>>> a[::-2]
[9, 7, 5, 3, 1]
メソッド
- append
- count
- extend
- index
- insert
- pop
- remove
- reverse
- sort
以上のメソッドを持っています。それぞれの役割は通常のドキュメントを参照のこと。
応用
リスト⇔タプル変換
>>> b
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> c = list(b)
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
注釈
タプルってなんなの?
イミュータブルな「リスト」です。 また、文字列もイミュータブルな「バッファ」です。 「リスト」は任意の型が混在でき、「バッファ」は一種類の型のみのシーケンスです。
「リスト」も「タプル」も「バッファ」もインデックスアクセスで1要素にアクセスできます。
>>> l = ['h', 'o', 'g', 'e']
>>> t = ('h', 'o', 'g', 'e')
>>> s = 'hoge'
>>> l[2]==t[2]==s[2]
True
参照に関して差のないこれらは、書き換えのときに挙動の差があります。
>>> l = ['h', 'o', 'g', 'e']
>>> t = ('h', 'o', 'g', 'e')
>>> s = 'hoge'
>>> l[2] = 'h'
>>> t[2] = 'h'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: object does not support item assignment
>>> s[2] = 'h'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: object does not support item assignment
つまりイミュータブルというのは「書き換え不可能」という制約のようなもので、 この制約のおかげで生まれる利点もあるということです。
文字列の一文字を書き換えできないというのは 他の著名な言語と比べるとびっくりするかもしれませんね。
1列のリストをペアのリストに変換
>>> b
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
zip関数はZipFileとは関係なく、ジグザグにミックスするための関数です。
zipのヘルプを見てもらえれば、トリオもカルテットもできることがわかるでしょう。
ソートと逆順
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a.reverse() >>> a [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> a.sort() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a.sort(reverse=True) >>> a [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
ソートしたり、リバースしたあと、イテレーションにて各要素にアクセスする予定があるなら、 ジェネレータによる遅延評価スタイルがお勧めです。
>>> a = range(10)
>>> for i in reversed(a):
... print i
...
9
8
7
6
5
4
3
2
1
0
>>> for i in sorted(a,reverse=True):
... print i
...
9
8
7
6
5
4
3
2
1
0
これらの方法では、一括して並べ替えを行うのではなく、 1要素の取得を要求するごとに必要最低限の処理をしてその要素を取り出していきます。 「ジェネレータ」という仕組みを仲介しているからなんですが、
これらの方法による利点は3つ。
- リストでもタプルでも参照元シーケンスに用いることができる
- 参照元を変化させない(複製しなくてよい)
- ジェネレータの利点が得られる
要素の重複を取り除く
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8]
>>> b = set(a)
>>> b
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a = list(b)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
この例のように、一旦セットオブジェクトにして戻してやると、 重複要素を取り除くことができます。
所感
シーケンスオブジェクトって、意外に多様なニーズがあるんですが、 Pythonではそれらをリスト、タプル、バッファ、ジェネレータの 4種でうまくカバーしていると思います。
応用例は今後ちょくちょく追加します。