Lesson08 リストと for 文
データのセットをとループ処理を学ぼう
- リストと for 文
- ネストされたリストのループ
- 長いリストを別ファイルにする
リストは、その構造上、反復に適しています。今回は、リストの要素に様々な反復しやすいデータをセットし、それをループで反復処理する方法を学びます。
今使うソースコードはここからまとめてダウロードできます。 ダウンロードfile_download
前回の復習
前回はリストというデータの構造について学びました。
前回出た重要キーワード
- リスト
- インデックス
- リストの要素
- リストの要素の変更
- リストへの要素の追加、append
- リストのリスト(リストのネスト)
- リストは、箱が連なったような構造をしたデータです。
- リストは先頭から 0 番目、1 番目、・・・と順番がついていて、それをインデックスといいます。
- インデックスが N 番目の要素はリストにつけた名前を array とすると array[N] になります。
- N 番目の要素を書き換えるときは、array[N]=書き換える中身、のように=で代入します。
- ‘A’ をリストの末尾に追加するときは、array.append(‘A’) とします。=で代入するのではないので注意します。
1リストと for 文
1.1 リストを for 文で回す
これまで for 文は range 関数を使ってループする文として学習しました。実は、range のところにリストを置くと、そのリストの要素の内容でループ変数を変更しながらループで反復します。
たとえば、fruitsというフルーツの名前を要素にもつリストを考えましょう。このリストは要素が 4 つなので、この要素を列挙するプログラムは下記のようになります。
lesson008_8.py
1 2 3 4 5 6 7 8 |
fruits = [ 'apple', 'orange', 'banana', 'melon', ] for k in range(0,4): print(fruits[k]) |
---|
しかし、いつも要素の数を人間が数えて range 関数にセットするのは、ばかばかしい気がします。range の 2 つ目の引数は、リストの場合、リストの末尾のインデックス+1であり、これはリストの要素の個数と一致します。よって、
for ループ変数 in range(0,len(リスト)) : # ループ変数はリストのインデックスが順番にセットされる
とすると、リストの要素全部に対して処理を行えます。
lesson008_9.py
1 2 3 4 5 6 7 8 |
fruits = [ 'apple', 'orange', 'banana', 'melon', ] for k in range(0,len(fruits)): print(fruits[k]) |
---|
しかし、毎回インデックスでアクセスするのは少々めんどくさいですね。リストの要素を直接ループで処理する方法があります。
for ループ変数 in リスト : # ループ変数にはリストの要素が入る。
とするとインデックスを利用しないでループできます。
lesson008_10.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
president = [ "", '伊藤博文', '黒田清隆', '山縣有朋', '松方正義', '伊藤博文', '松方正義', '伊藤博文', '大隈重信', '山縣有朋', '伊藤博文', '桂 太郎', '西園寺公望', '桂 太郎', '西園寺公望', '桂 太郎', '山本權兵衞', '大隈重信', '寺内正毅', '原敬', '高橋是清', ] |
---|
このリストを例に説明しましょう。
先頭の要素(インデックスが 0 の要素)から末尾の要素までを、順に反復処理するプログラムを考えます。反復処理の内容は、要素の中身を表示することにします。
最後の for 文は次のようにもかけます。
lesson008_10.py
1 2 |
for name in president: print(name) |
---|
実行結果
1 2 3 4 5 6 |
伊藤博文 黒田清隆 山縣有朋 …中略… 原敬 高橋是清 |
---|
インデックスと要素の中身を同時に取り出せる enumerate(英語で「列挙する」の意) という関数もあります。
for インデックスの番号 ,それに対応するリストの中身 enumerate(リスト) :
lesson008_20.py
1 2 |
for k,name in enumerate(president): print(str(k)+"代総理大臣は "+ name) |
---|
実行結果
1 2 3 4 5 6 7 |
0 代総理大臣は 1 代総理大臣は 伊藤博文 2 代総理大臣は 黒田清隆 3 代総理大臣は 山縣有朋 …中略… 19代総理大臣は 原敬 20代総理大臣は 高橋是清 |
---|
要素の数は 21 個、つまりインデックスの最後は 20 であることがわっていれば、インデックスでループもできます。
lesson008_30.py
1 2 |
for k in range(1,21): print(str(k)+"番目の総理大臣は"+ president[k]) |
---|
1.2 ネストされたリストのループ処理
ネストされたリストへのアクセス方法
リストの変数 [外側のインデックス] [ネスト1階層目のインデックス] [ネスト2階層目のインデックス] [ネスト3階層目のインデックス]…
ネストされたリストは、インデックスを左から右にネストが深くなる順でインデックスを指定します。
具体的な例でみていきましょう。
このデータから男性の平均寿命が 80 歳未満の都道府県名をリストアップしてみましょう。下記のファイルは、age.py として保存されています。そこからコピーしましょう。
age.py
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 34 35 36 37 38 39 40 41 41 43 44 45 46 47 48 49 |
ranking = [ ['滋賀県','81.78','87.57'], ['長野県','81.75','87.67'], ['京都府','81.40','87.35'], ['奈良県','81.36','87.25'], ['神奈川県','81.32','87.24'], ['福井県','81.27','87.54'], ['熊本県','81.22','87.49'], ['愛知県','81.10','86.86'], ['広島県','81.08','87.33'], ['大分県','81.08','87.31'], ['東京都','81.07','87.26'], ['石川県','81.04','87.28'], ['岡山県','81.03','87.67'], ['岐阜県','81.00','86.82'], ['宮城県','80.99','87.16'], ['千葉県','80.96','86.91'], ['静岡県','80.95','87.10'], ['兵庫県','80.92','87.07'], ['三重県','80.86','86.99'], ['山梨県','80.85','87.22'], ['香川県','80.85','87.21'], ['埼玉県','80.82','86.66'], ['島根県','80.79','87.64'], ['新潟県','80.69','87.32'], ['福岡県','80.66','87.14'], ['佐賀県','80.65','87.12'], ['群馬県','80.61','86.84'], ['富山県','80.61','87.42'], ['山形県','80.52','86.96'], ['山口県','80.51','86.88'], ['長崎県','80.38','86.97'], ['宮崎県','80.34','87.12'], ['徳島県','80.32','86.66'], ['北海道','80.28','86.77'], ['茨城県','80.28','86.33'], ['沖縄県','80.27','87.44'], ['高知県','80.26','87.01'], ['大阪府','80.23','86.73'], ['鳥取県','80.17','87.27'], ['愛媛県','80.16','86.82'], ['福島県','80.12','86.40'], ['栃木県','80.10','86.24'], ['鹿児島県','80.02','86.78'], ['和歌山県','79.94','86.47'], ['岩手県','79.86','86.44'], ['秋田県','79.51','86.38'], ['青森県','78.67','85.93'], ] |
---|
都道府県名、男性の平均寿命、女性の平均寿命を列記する。
lesson008_40.py
1 2 3 4 5 |
for k in range(0,47): prefecture_name = ranking[k][0] male_age = float(ranking[k][1]) female_age = float(ranking[k][2]) print(prefecture_name + str(male_age) + " "+str(female_age)) |
---|
実行結果
1 2 3 4 |
・・・ 和歌山県79.94 86.47 岩手県79.86 86.44 秋田県79.51 86.38 |
---|
男性寿命が最大の県を見つけてみましょう。ループの中で暫定最大値(暫定の最高年齢)となる変数を max 、その都道府県名を max_name とします。max よりも大きい値がみつかったら、その値で max を置き換えていきます。
lesson008_50.py
1 2 3 4 5 6 7 8 9 10 11 |
max = 0 #ループで回っている最新の最大値 max_name ="" #ループで処理している最新の最大値をもつ都道府県名 for k in range(0,47): prefecture_name = ranking[k][0] male_age = float(ranking[k][1]) if male_age > max : max = male_age max_name = prefecture_name print(str(max_name)+"の"+str(max)+"歳が最長平均寿命です") |
---|
実行結果
1 | 滋賀県の81.78歳が最長平均寿命です |
---|
実は最大値をみつけるだけであれば、max という関数を使うと便利です。max は次のように使います。
変数 = max(数値を要素に持つリスト)
#変数には様要素の中で最大の要素の値がセットされる
max 関数の使い方(lesson008_60.py)
1 2 |
data_array =[1 ,2 ,3.1 ,5.1 , 3.9 , 0.8 , 4.6] print("最大値は"+str(max(data_array))) |
---|
実行結果
1 | 最大値は5.1 |
---|
この関数 max をつかって lesson008_50.py と同じ最大値を求めるソースを書いてみましょう。ただし、男性の最大寿命をとる都道府県名は表示しなくてよいです。
【ミニ演習】
lesson008_70.py と保存して下さい。
lesson008_70.py
1 2 3 4 5 6 7 |
male_array =[] for k in range(0,47): male_age = ????(ranking[k][1]) ???? max = max(male_array) print(str(max)+"歳が最長平均寿命です") |
---|
実行結果
1 | 81.78歳が最長平均寿命です |
---|
でも、どの都道府県かこの方法ではわかりません。
1.3 長いリストを別ファイルにする
先ほどの内閣総理大臣の一覧をリストにした president ですが、これを president.py のファイル名で保存します。
president.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
president = [ "", '伊藤博文', '黒田清隆', '山縣有朋', '松方正義', '伊藤博文', '松方正義', '伊藤博文', '大隈重信', '山縣有朋', '伊藤博文', '桂 太郎', '西園寺公望', '桂 太郎', '西園寺公望', '桂 太郎', '山本權兵衞', '大隈重信', '寺内正毅', '原敬', '高橋是清', ] |
---|
長いリストのデータを別ファイルにするには以下のようにします。
from ファイル名(.pyは書かない) import リスト名
こうすると処理だけを分けて書くことができます。
lesson008_80.py
1 2 3 |
from president import president for name in president: print(name) |
---|
演習の時間
演習の解答はここからダウンロードできます。ダウンロードfile_download
演習1
次のような整数を要素に持つリスト array があります。このリストで、奇数かつ最小の要素を見つけ出すプログラムを書いてください。enshu008_01.py と保存して下さい。
1 2 3 4 5 6 7 8 9 10 11 |
array =[ 100, 200, 98, 77, 32, 5, 4, 88, 233, ] |
---|
暫定の最小値 : min
ある数 nが奇数であること n % 2 == 1
期待される動作
最小値は5です
演習2
先生より世界の国別携帯電話の契約台数のデータをもらってください。
データの 1 行を先頭に書くことで、この ranking というリストを使えるようにしてからコードを書きましょう。
この ranking ですが、リストの要素はさらにネストで、それぞれ先頭から順位、国名、携帯電話の契約件数(単位:万件)が入っています。
1 2 3 4 5 |
ranking = [ ['1','中国','164,114.7'], ['2','インド','117,602.2'], … ] |
---|
たとえば第 1 位は中国で、その数は、16億4114万7千件です。
世界の上位5位までの国の契約台数が、データ内の全ての国の契約台数のうちの何パーセントを占めるかを計算してください。携帯はある意味富や情報インフラの指標となりますが、一部の国にその富や情報インフラが集中していることをこの統計から実感してみましょう。人口が多い国ほど契約数も多いので、本当は契約数を人口でわって、人口 10 万人あたりの契約数などで比較するのが公平な評価でしょう。enshu008_02.py と保存して下さい。
ヒント
まず、世界の全契約台数を保持する変数 S と 上位 5 位までの国の契約台数合計を保持する top5goukei という変数を用意します。
前回やった奇数の総和のプログラムのように、それぞれ S, top5goukei を求めてみましょう。
期待される動作
1位: 中国164114.7 2位: インド117602.2 3位: 米国40457.7 4位: インドネシア32077.0 5位: ロシア連邦22943.1 上位 5 カ国の合計は 163 カ国の XX %です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from mp import ranking S = 0 #全世界の契約台数の合計を表す変数 top5goukei = 0 #上位5カ国の契約台数の合計を表す変数 for k in range(0,163): junni = int(ranking[?][?]]) kuni = ranking[?][?] keitaidenwa = float(????) S = S + ???? if junni < 6 : print(str(junni)+"位: "+ kuni + str(keitaidenwa)) top5goukei = top5goukei + ???? #上位5カ国のときに和をとる wariai = top5goukei/S*100 print("上位5カ国の合計は、163カ国の" + str( wariai ) + "%です") |
---|
ヒント
ループを横断して使う変数 junni, kuni, keitaidenwa は何を表す変数でしょうか?
時間があまったあなたに
円周率で遊んでみよう!
円周率 π は、小数の表示にしても途切れることなくずっと続くことは知っていますね。
3 分の1のように0.333…と循環するのであればわかりますが、循環もせず永遠に違うパターンでつづくというのは不思議な気がします。さて、その数字の並びにパターンはあるのでしょうか。ちょっと遊んでみましょう。
pi.py は、円周率を小数点以下 100 万桁まで 10 桁ずつをリストにしたデータで、10 万個の要素を持っています。
10 桁ずつくぎったこの要素のなかで最大の数値はなんだと思いますか?
9999999999 だと思うかもしれませんが、この並びは出てきません。python で調べてみましょう。要素は文字列であることに注意しましょう。(ad_008_1.py)