リストのいろいろ

リストのいろんな使い方

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モジュールを使いましょう!

長さを調べる

10

注釈

ここが、よくオブジェクト指向じゃない!と突っ込まれやすいですが、 内部機構はオブジェクト指向的です。

参照

インデックス参照

>>> 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]

この例のように、一旦セットオブジェクトにして戻してやると、 重複要素を取り除くことができます。

合計値の取得

45

floatと、intなどが混在していても大丈夫ですが、strなどが入っているとエラーになります。 ひとつでもfloatが含まれていると結果もfloatになります。

所感

シーケンスオブジェクトって、意外に多様なニーズがあるんですが、 Pythonではそれらをリスト、タプル、バッファ、ジェネレータの 4種でうまくカバーしていると思います。

応用例は今後ちょくちょく追加します。