Pythonのデータ構造について学んでいきます
データ構造とは、データを整理して保存する方法のことです
Pythonにはいくつかの基本的なデータ構造があり、データ構造を使うことでデータを効率よく整理し、操作することができるようになります
この章では、リストとタプルについて説明します
リスト
リストは、複数の要素(値)を順序付きで格納できるデータ構造です
格納された各データのことを要素
と言います
リストの性質は以下の通りです
- 複数のデータを管理できる
- リストの要素には順番(インデックス)がついているため、インデックスを用いて要素を指定することができる
- リストの要素を変更することができる
- リストに要素を追加したり、削除することができる
リストの作成方法
1.[](角括弧)
を使用する
リストを作成するには、[ ] (角括弧)間に、格納する要素をカンマで区切って並べます
作成したリストをあとで使用するため、変数に代入し以下のように記述します
a = [1,2,3,4,5]
print(a)
print(type(a))
実行結果
[1, 2, 3, 4, 5]
<class 'list'>
1,2,3,4,5をまとめたリストaが作成され、型がlistになっています
[]の中に何も書かない場合は、空のリストが作成されますa = []
print(a)
print(type(a))
実行結果
[]
<class 'list'>
リストには、文字列を指定することもできます
s1 = ["Tokyo","Osaka","Nagoya"]
print(s1)
print(type(s1))
実行結果
['Tokyo', 'Osaka', 'Nagoya']
<class 'list'>
リストの要素には、異なる型の値を混ぜて格納することもできです
a = ["orange",3,128]
print(a)
print(type(a))
実行結果
['orange', 3, 128]
<class 'list'>
”orange”、3、128をまとめたリストaが作成され、型がlistになっています
このサンプルプログラムのように、型が異なっている要素をまとめることもできます
2.list(リスト)関数を使用する
list関数はリストを作成するための別の方法です
list関数は空のリストを作成したり、他のデータ型(文字列やタプルなど)をリストに変換するために使うことができます
たとえば、文字列を格納したリストを作成する場合、以下のように記述することができます
s = list("ABCDEF")
print(s)
print(type(s))
実行結果
['A', 'B', 'C', 'D', 'E', 'F']
<class 'list'>
また、range関数を利用して、連続した数値をもったリストを作成する場合、以下のように記述することができます
l = list(range(1,11))
print(l)
print(type(l))
実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
<class 'list'>
リストの要素数の取得にはlen関数を使用します
l = list(range(1,11))
n = len(l)
print("要素数:" + str(n))
実行結果
要素数:10
インデックスとスライス
リストの各要素にアクセスするには、文字列同様に、インデックスやスライスを適用できます
インデックス、開始インデックス、終了インデックスの使い方は文字列の場合と同様です
リストから指定した位置の要素を取り出す場合
リスト[インデックス]
リストの一部をスライスで取り出す場合
リスト[開始インデックス:終了インデックス]
以下に、インデックスを用いてリストから要素を取り出すサンプルプログラムを示します
s1 = ["Tokyo","Osaka","Nagoya"]
print("インデックス:0~2")
print(s1[0])
print(s1[1])
print(s1[2])
print("インデックス:-1~-3")
print(s1[-1])
print(s1[-2])
print(s1[-3])
print("スライス")
print(s1[1:3])
実行結果
インデックス:0~2
Tokyo
Osaka
Nagoya
インデックス:-1~-3
Nagoya
Osaka
Tokyo
スライス
['Osaka', 'Nagoya']
要素の更新・追加や削除
リストの一部の要素を変更する場合インデックスを使用して以下のように記述します
リスト[インデックス]=式
たとえば、”coffee”,”tea”,”water”を持ったリストを作成し、3番目の”water”を”milk”に変更してみます
s1 = ["coffee","tea","water"]
print(s1)
s1[2] = "milk"
print(s1)
実行結果
['coffee', 'tea', 'water']
['coffee', 'tea', 'milk']
waterがmilkに変更できました
リストに要素を追加することもできます
しかし下記のように記述するとエラーが発生します
s1 = ["coffee","tea","water"]
s1[3] = "juice"
インデックスの存在しない番号への代入や取得はできません
要素をリストの末尾に追加する場合はappend関数を使用して以下のように記述します
リスト.append(値)
では、上で作成したリスト[“coffee”,”tea”,”milk”]に”juice”を追加してみましょう
s1.append("juice")
print(s1)
実行結果
['coffee', 'tea', 'milk', 'juice']
要素をリストの特定の場所に挿入する場合はinsert関数を使用して以下のように記述します
リスト.insert(挿入する位置のインデックス,値)
たとえば、[‘coffee’, ‘tea’, ‘milk’, ‘juice’]の”coffee”の前に挿入する場合
s1.insert(0,"water")
print(s1)
実行結果
['water', 'coffee', 'tea', 'milk', 'juice']
インデックス0番目に値を挿入がされています
指定した要素を削除する場合はremove関数を利用します
リスト.remove(値)
remove関数は、リストの先頭から指定した値の要素を探し見つかったら削除し、見つからなかった場合エラーを返します
リストに重複した値があった場合は、初めに見つかった要素だけが削除されます
s2 = ['water', 'coffee', 'tea', 'milk', 'tea']
print(s2)
s2.remove("tea")
print(s2)
実行結果
['water', 'coffee', 'tea', 'milk', 'tea']
['water', 'coffee', 'milk', 'tea']
s2.remove("cola")
ループ処理でのリスト
for文を利用してリストの要素を一つずつ取り出すことができます
for 要素 in リスト:
処理A
for文とinを使い上記のように記述します
drink = ['water', 'coffee', 'tea', 'milk', 'tea']
for item in drink:
print("飲み物:"+item)
実行結果
飲み物:water
飲み物:coffee
飲み物:tea
飲み物:milk
飲み物:tea
ソート
リストにはソート処理を簡単に行うことができます
ソートには、自分自身をソートする方法とソートされたリストを作成する方法とがあります
1.自分自身をソート
# 昇順
リスト.sort()
# 逆順
リスト.sort(reverse=True)
昇順の場合は引数がなく、逆順の場合はreverse=Trueを指定します
l = ['g', 'b', 't', 'w', 's']
print("ソート前")
print(l)
l.sort()
print("ソート後")
print(l)
print("逆順ソート後")
l.sort(reverse=True)
print(l)
実行結果
ソート前
['g', 'b', 't', 'w', 's']
ソート後
['b', 'g', 's', 't', 'w']
逆順ソート後
['w', 't', 's', 'g', 'b']
ソートは辞書順に行われます
2.ソートされたリストの作成
# 昇順
sorted(リスト)
# 逆順
sorted(リスト,reverse=True)
l = ['g', 'b', 't', 'w', 's']
print("ソート前")
print(l)
l1 = sorted(l)
print("ソート後")
print(l1)
l2 = sorted(l,reverse=True)
print("逆順ソート後")
print(l2)
print("オリジナル")
print(l)
実行結果
ソート前
['g', 'b', 't', 'w', 's']
ソート後
['b', 'g', 's', 't', 'w']
逆順ソート後
['w', 't', 's', 'g', 'b']
オリジナル
['g', 'b', 't', 'w', 's']
はじめに定義したリストの値は変更されていないことがわかります
【演習問題】
リストの要素を[4, 1, 3, 1, 12, 8, 10, 9, 7, 7]と定義し以下の問題を実施しましょう
- インデックスを指定して12を取り出してみましょう
実行結果
12
- 5を末尾に追加してみましょう
実行結果
[4, 1, 3, 1, 12, 8, 10, 9, 7, 7, 5]
- 4と1の間に6を挿入してみましょう
実行結果
[4, 6, 1, 3, 1, 12, 8, 10, 9, 7, 7, 5]
- はじめに出現する7を削除してみましょう
実行結果
[4, 6, 1, 3, 1, 12, 8, 10, 9, 7, 5]
- 昇順でソートしてみましょう
実行結果
[1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 12]
タプル
タプルはリストと同様に順序つけられた複数の値を格納することができますが、作成後に更新や挿入、削除など要素を変更することができません
このため、データの変更を防ぎたい場合に使います
特徴は次の通りです
- 要素の追加や削除ができない
- 中⾝の要素を変更したくないときに使⽤する
- メモリ消費量が少ない
- インデックスで値を取得できる
- アンパックで複数の値を取り出すことができる
タプルの作成方法
タプルは、( )丸括弧 を使って、( ) 間に、格納する要素をカンマで区切って並べます
作成したタプルをあとで使用するには、変数に代入し以下のように記述します
a = (1,2,3,4,5)
print(a)
print(type(a))
実行結果
(1, 2, 3, 4, 5)
<class 'tuple'>
1,2,3,4,5をまとめたリストaが作成され、型がtupleになっています
v = (1)
print(type(v))
t = (1,)
print(type(t))
実行結果
<class 'int'>
<class 'tuple'>
要素が一つしかないタプルを定義する場合は値の後にカンマが必要です
()の中に何も書かない場合は、空のタプルが作成されます
a = ()
print(a)
print(type(a))
実行結果
()
<class 'tuple'>
tuple関数を利用してタプルを作成することもできます
a = tuple()
print(a)
print(type(a))
実行結果
()
<class 'tuple'>
1から10までの整数を格納したタプルを以下のようにして作成することもできます
t = tuple(range(1,11))
print(t)
実行結果
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
インデックスやスライスはタプルにも使うことができます
使い方はリストと同じなので割愛します
パック・アンパック
複数の値をタプルにまとめることをパック(またはパッキング)と言います
逆にタプルにまとめた複数の値を分解する操作のことをアンパック(またはアンパッキング)と言います
アンパックは以下のように記述します
タプルの各要素を複数の変数に代入することができます
変数,,, = タプル
たとえば、以下のような使い方ができます
menu = ("coffee",350)
item,price = menu
print(item)
print(price)
実行結果
coffee
350
タプルをアンパックし、変数itemとpriceにそれぞれ代入することができました
要素の個数の多いタプルから先頭や末尾の要素だけを取り出したいときがあります
そんな時は、代入先の中に*(アスタリスク)がついた変数を含めて、以下のように記述します
# 先頭の要素を取得
変数,*変数 = タプル
# 末尾の要素を取得
*変数, 変数 = タプル
# 先頭と末尾の要素を取得
変数, *変数 , 変数 = タプル
menu = ("coffee","tea","water","milk")
# 先頭の要素の取得
first, *other = menu
print(first)
print(other)
print("*"*10)
# 末尾の要素の取得
*other,last = menu
print(other)
print(last)
print("*"*10)
#先頭と末尾の要素の取得
first,*other,last = menu
print(first)
print(other)
print(last)
実行結果
coffee
['tea', 'water', 'milk']
**********
['coffee', 'tea', 'water']
milk
**********
coffee
['tea', 'water']
milk
先頭の要素の取得では、先頭の要素をfirstに代入し残りの要素をotherに代入しています
末尾の要素の取得では、末尾の要素をlastに代入し、先頭から末尾の要素の一つ前までをotherに代入しています
先頭と末尾の要素の取得では、先頭の要素をfirstへ、末尾の要素をlastへ、残りの要素をotherに代入しています
※アンパックはリストでも同様の記述をすることができます
リストとタプルの相互変換
タプルからリストへ、リストからタプルへの変換について説明します
1.タプルからリストへ
タプルからリストを生成する場合、list関数を使用します
menu = ("coffee","tea","water","milk")
menulist = list(menu)
print(menulist)
print(type(menulist))
実行結果
['coffee', 'tea', 'water', 'milk']
<class 'list'>
2.リストからタプルへ
リストからタプルを生成する場合はtuple関数を使用します
numlist = list(range(1,11))
numtuple = tuple(numlist)
print(numtuple)
print(type(numtuple))
実行結果
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
<class 'tuple'>
データ構造を組み合わせた構造
あるデータ構造の中に別のデータ構造を入れた階層的なデータ構造を作ることにより複雑なデータ構造を管理することができます
たとえば、リストの中にタプルを入れたり、リストの中にリストを入れたり、タプルの中にリストを入れたりすることです
任意のデータ構造を何階層でも必要なだけ組み合わせることができます
リストの中にタプルを入れたサンプルプログラムを以下に示します
menulist = list()
t = ("coffee",350)
menulist.append(t)
t = ("tea",300)
menulist.append(t)
t = ("water",250)
menulist.append(t)
t = ("milk",200)
menulist.append(t)
t = ("juice",150)
menulist.append(t)
t = ("milk",200)
menulist.append(t)
print(menulist)
for item in menulist:
menu,price = item
print(menu + "の値段は" + str(price) + "円です。")
実行結果
[('coffee', 350), ('tea', 300), ('water', 250), ('milk', 200), ('juice', 150), ('milk', 200)]
coffeeの値段は350円です。
teaの値段は300円です。
waterの値段は250円です。
milkの値段は200円です。
juiceの値段は150円です。
milkの値段は200円です。
少々複雑ですので、いくつか説明をしていきます
menulist = list()
menulistという空のリストを生成します
t = ("coffee",350)
menulist.append(t)
coffeeと250の要素をもったタプルを作成しmenulistの末尾に追加します
for item in menulist:
menulistから要素1つずつを取り出します
取り出したitemはmenulistに追加したタプルです
menu,price = item
タプルをアンパックし変数menuとpriceにそれぞれ代入しています
【演習問題】
タプルの要素を(4, 1, 3, 1, 12, 8, 10, 9, 7)と定義し以下の問題を実施しましょう
- インデックスを指定して12を取り出してみましょう
実行結果
12
- スライスを指定して(8,10,9,7)を取り出してみましょう
実行結果
(8, 10, 9, 7)
- 本日の総売上を計算するプログラムを書いてみましょう
本日の売上の項目、単価、数量は次の表の通りです
menu | 単価 | 数量 |
coffee | 350 | 2 |
tea | 300 | 4 |
water | 0 | 5 |
milk | 200 | 1 |
juice | 150 | 2 |
milk | 200 | 3 |
実行結果
[('coffee', 350, 2), ('tea', 300, 4), ('water', 0, 5), ('milk', 200, 1), ('juice', 150, 2), ('milk', 200, 3)]
合計金額:3000円
コメント