前回の記事で、変数や代入する値に対する種類(型)について説明しました。
今回は多数の値をまとめて管理するデータ構造についてのお話したいと思います。
データ構造ってなんだか難しそうな単語が出てきたよ、説明聞いてわかるかな。。。
言葉は難しそうですが、説明しちゃえばそんなに難しいものではないです。
なので、今回も例を踏まえてなるべく分かりやすく解説しますね。
- Pythonでのデータ構造や種類
- リスト、タプル、セットの違いや使い方が分かる
データ構造とは何か
データ構造とは「複数の値(数値や文字列など)をひとまとまりとして使う方法」のことを言います。
プログラムをかじったことのある方であれば「配列」や「リスト」という言い方をすればピンとくるかもしれません。
例えば、あるクラスの生徒の名前を管理するプログラムを書くとします。
student1 = "Yamada Taro"
student2 = "Suzuki Hanako"
student3 = "Sakuma Takeru"
print(student1 ,student2 ,student3) # Yamada Taro Suzuki Hanako Sakuma Takeru
変数を生徒分用意して名前を表示するだけのプログラムです、簡単ですよね。
ただこれ、もしクラスに生徒が40人いたらどうでしょうか?
もっと言うと、生徒もクラスだけじゃなくて学年全体や全校生徒全員の名前を管理したいとなった場合はどうでしょうか?
その場合、変数宣言だけでもものすごい数になりますし、またその変数全てを管理しないといけません。
いちいちそんな面倒なことしてられませんよね。
じゃあどうするか
変数の型が同じなのであれば、1個の変数にまとめちゃいましょう。
student = ["Yamada Taro","Suzuki Hanako","Sakuma Takeru"]
print(student[0] ,student[1] ,student[2]) # Yamada Taro Suzuki Hanako Sakuma Takeru
データを1つの変数にまとめたことで、管理する変数が1つになりました。
このように複数の値を一定の形式にまとめることをデータ構造と呼びます。
データ構造の種類について
Pythonではデータ構造にもいくつかの種類がありますので、そちらを説明していきたいと思います。
具体的には以下の3つです。
(厳密にいうと辞書やレンジもデータ構造に入りますが、まずは基本として下記3つを覚えておきましょう)
- リスト
- タプル
- セット
リスト
リストとは動的配列のことを言います。
つまり、要素内を自由に追加したり削除したりすることが出来ます。
Javaで言うと「ArrayList」のようなイメージです。
リストの作成
では実際にリストを使ってみましょう。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten']
これは「name」と言うリストの中に「Son Goku」,「Son Gohan」,「Son Goten」と3つの値を入れています。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name[0]) # Son Goku
print(name[1]) # Son Gohan
print(name[2]) # Son Goten
リスト内の値を取り出す場合は上記2〜4行目のようにその変数名の後ろに[数字]を指定します。
リストでは値を入れた順番にインデックス値が設定されるため、値の最初から順に0,1,2….と番号が振られます。
ここで注目して頂きたいのはリスト内に振られているインデックス値は「1」ではなく「0」から始まります。
ここ非常に間違えやすいので注意しましょう。
リストの値を変更
ではリスト内の値を変更してみましょう。
例えば、2番目の要素(インデックス番号1)を”Son Gohan”→”kuririn”に変更してみます。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten']
name[1] = "kuririn"
print(name) # ['Son Goku', 'kuririn', 'Son Goten']
リスト内の値を変更したい場合は、変更したいリスト内の要素をインデックスで指定して、その変数に値を直接入力します。
上記で言うと、4行目の「name[1] = “kuririn”」のところで2番目の要素を変更しています。
リストの値を追加
リスト内に値を追加したい場合はどうするのでしょうか。
値を追加したい場合は下記のようにメソッドを使います。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten']
name.append("Piccolo")
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten', 'Piccolo']
name.insert(1,"Vegeta")
print(name) # ['Son Goku', 'Vegeta', 'Son Gohan', 'Son Goten', 'Piccolo']
実際に追加するメソッドは4行目のappendと7行目のinsertです。
どちらも要素を追加するメソッドですが、以下の違いがあります。
- append → リストの一番後ろに要素を追加する
- insert → リストをインデックス指定してその位置に要素を追加する
上記で言うと、リストの一番後ろにピッコロを、2番目(インデックス番号1)にベジータを追加しています。
リストの値を削除
では次にリストの値を削除してみましょう。
削除する場合も追加と同様にメソッドを使います。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten']
name.remove("Son Goten")
print(name) # ['Son Goku', 'Son Gohan']
del name[1]
print(name) # ['Son Goku']
name.clear()
print(name) # []
実際に削除するメソッドは4行目のremoveと7行目のdelと10行目のclearです。
どれも値を削除するメソッドですが、以下の違いがあります。
- remove → 値を直接指定してリスト内のその値を削除する
- del → 値をインデックス指定してリスト内のその値を削除する
- clear → リスト内の値を全て削除する
上記だと、removeで「Son Goten」を削除、delで2番目の要素(インデックス1番目)を削除、clearでリスト内の全ての要素を削除しています。
その他のメソッド
要素の追加や削除以外にもPythonのリストには色々なメソッドがあります。
よく使うものを挙げると以下があります。
name = ["Son Goku","Son Gohan","Son Goten"]
print(name) # ['Son Goku', 'Son Gohan', 'Son Goten']
"Son Goku" in name # True
name[0:2] # ['Son Goku', 'Son Gohan']
len(name) # 3
4行目の「in リスト名」とすると、リスト内の値を検索出来ます。
「Son Goku」はリストの中にあるのでbool型のTrueを返しています。
6行目の「name[0:2]」はリスト内の開始位置0番目から終了位置2番目を指定して、その要素を抜き出しています。
8行目の「len」はリスト内の要素数を返すメソッドで、3つ入っているので3を返しています。
- 値 in リスト → リスト内に値があるか検索する
- リスト[x:y] → 開始位置xから終了位置yまでを取得する
- len(リスト) → リスト内の要素数を返す
タプル
タプルとはリストとよく似ていますが、リストと異なる点は値の変更が出来ません。
また要素の追加や削除、値の変更も出来ません。
タプルの作成
タプルを作成する場合は、リストと異なり要素を「( )」で括ります。
name = ("Son Goku","Son Gohan","Son Goten")
print(name) # ('Son Goku', 'Son Gohan', 'Son Goten')
print(name[1]) # Son Gohan
値を指定して取り出す際はインデックスで要素を指定するなど、使い方はリストと同じです。
タプルの要素の追加・削除・変更
では、タプルの値を変更してみるとどうなるでしょう。
実際に先ほどリストで行なった要素の変更をタプルで実行してみるとエラーとなります。
name = ("Son Goku","Son Gohan","Son Goten")
print(name) # ('Son Goku', 'Son Gohan', 'Son Goten')
name[1] = "kuririn" # TypeError: 'tuple' object does not support item assignment
また要素の追加や削除も同様にエラーとなります。
name = ("Son Goku","Son Gohan","Son Goten")
print(name) # ('Son Goku', 'Son Gohan', 'Son Goten')
name.append("Piccolo") # AttributeError: 'tuple' object has no attribute 'append'
del name[1] # TypeError: 'tuple' object doesn't support item deletion
よって、タプルは要素の追加、削除、変更が出来ないことが分かります。
その他のメソッド
要素の追加、削除、変更以外のメソッドに関しては、リストと同様のメソッドが使えます。
name = ("Son Goku","Son Gohan","Son Goten")
print(name) # ('Son Goku', 'Son Gohan', 'Son Goten')
"Son Goku" in name # True
name[0:2] # ('Son Goku', 'Son Gohan')
len(name) # 3
使い方はリストと同じです。
タプルの用途
タプルはリストに比べて要素の追加、削除、変更が出来ないといった機能が制限されています。
じゃあわざわざタプルを使わなくてもリストでいいんじゃないの、何のためにタプルがあるの?
おっしゃる通り、タプルはリストに比べて要素の変更が出来ない分機能的に劣りますので、普通にプログラムで使う分にはリストで問題ありません。
ではなぜタプルが存在するのでしょうか。
それは「リストで値を変えたくない時にタプルを使う」からです。
例えは、1週間を表すデータ構造を使う場合にどうするでしょうか。
week = [Sun, Mon, Tue, Wed, Thu, Fri, Sat] # ✖️リストで作ると要素が追加・変更・削除が出来る
week = (Sun, Mon, Tue, Wed, Thu, Fri, Sat) # ○リストで作ると要素が追加・変更・削除が出来ない
1週間は日曜日、月曜日、火曜日、水曜日、木曜日、金曜日、土曜日です、これはどの国でも変わりません。
逆に言えば変えられると困ります。
なのでプログラマのミスでうっかり変わると困るようなデータ構造を使う場合にはリストではなくタプルを使うのが望ましいです。
セット
最後はセットです。
セットも複数の値を一括で管理すると言う点ではリストやタプルと同じですが、データの管理方法が少し異なります。
セットは値の順番は関係なく、また値を重複して保管しません。
Javaで言うと「HashSet」のような、各々の値をインデックスではなくハッシュ値で管理するようなイメージです。
セットの作成
では実際にセットを使ってみましょう。
セットを作成する場合は、リストやタプルと異なり要素を「{ }」で括ります。
(今回は分かりやすいように、文字列ではなく数字を値として使用します)
pi = {3,1,4,1,5,9,2,6,4,8,7,7,7,6,9,8,8,6,9,2,4,8} # セット
print(pi) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
pi = [3,1,4,1,5,9,2,6,4,8,7,7,7,6,9,8,8,6,9,2,4,8] # リスト
print(pi) # [3, 1, 4, 1, 5, 9, 2, 6, 4, 8, 7, 7, 7, 6, 9, 8, 8, 6, 9, 2, 4, 8]
セットとリストに同じ一桁のランダムな数字を複数入れて、その入れた値がどう違うかを比較してみましょう。
上がセット、下がリストです。
リストに入れた値は、入れた値が順番通りそのまま格納されていることがわかります。
対してセットの場合はどうでしょうか。
セットに入れた値は、順番は管理せず、重複も許容しないため、重複した値は1つにかつ代入した値の順番とは異なる順序で格納されています。
セットの要素の追加・削除
セットの変更に関しては、そもそも値の変更と言う概念がないため変更は出来ません。
セットでは値を追加・削除します。
追加・削除は下記メソッドを使います。
pi = {3,1,4,1,5,9,2,6,4,8,7,7,7,6,9,8,8,6,9,2,4,8} # セット
print(pi) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
pi.add(10) # 10を追加
print(pi) # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
pi.remove(1) # 1を削除
print(pi) # {2, 3, 4, 5, 6, 7, 8, 9, 10}
セットに値を追加する場合は4行目の「add」メソッドを使います。
またセット内の値を削除する場合は7行目の「remove」メソッドを使います。
その他のメソッド
要素の追加・削除以外のメソッドに関しては、リストと同様に使えます。
pi = {3,1,4,1,5,9,2,6,4,8,7,7,7,6,9,8,8,6,9,2,4,8} # セット
print(pi) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
4 in pi # True
len(pi) # 9
min(pi) # 1
max(pi) # 9
使い方はリストと同じです。
まとめ
今回はPythonのデータ構造について、具体的なリスト、タプル、セットの説明をしました。
次回はプログラム制御構文について記載したいと思います。