【Python】2次元リストの検索

Pythonでの2次元リストの検索に苦労しました。
初心者が無い頭で考えた方法なのでシロウト感満載ですが、やりたいことは一応できたので備忘録として残しておきます。

#やりたいこと
「○○市の天気を教えて」と話し掛けると、その都市の天気予報を答えてくれるチャットボットを作ってみました。

天気予報はLivedoor天気情報の[Weather Hacks](http://weather.livedoor.com/weather_hacks/)からJSONデータを取得するようにします。

Livedoor天気情報のURLは、
`http://weather.livedoor.com/forecast/webservice/json/v1?city=` + `都市No.`
の構成で出来ているため（例えば東京の場合は、http://weather.livedoor.com/forecast/webservice/json/v1?city=130010）、
都市名を都市No.に変換する必要があります。

そこで、都市名と都市NO.一覧のCSVファイルを読み込ませ、入力された都市名から都市No.を検索すればいいのではないかと思って、プログラムを書いてみました。

#環境

* Python 3.6.5
* AWS Cloud9

#CSVファイルの構成
都市リスト（citylist.csv）の構成は以下のとおりです。
札幌市から那覇市まで、A列に都道府県庁所在地、B列に都市No.が、入っています。
このリストを都市名で検索して、一致した都市の都市No.を返すようにしたいと思います。
※B列は0から始まるNo.もあるため、文字列にしておく必要があります。
![citylist.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/353289/555b9a1d-b226-4c26-94cf-a3cb518681b8.png)

#CSVファイルの読み込み
まず、CSVファイルを読み込んで、2次元リストに格納します。
Pythonモジュール「csv」をインポートし、readerメソッドでCSVファイルを読み込んで、中身を2次元リスト（配列）に格納します。
サンプルソースコードは下記のとおりです。
※都市リスト（citylist.csv）はPythonプログラムファイルと同じディレクトリに保存しています。

```.py
import csv

#都市リスト（citylist.csv）を読み込んで、リスト（data）に格納する。   
f = open("citylist.csv","r",encoding="SHIFT-JIS")
reader = csv.reader(f)
data = [ e for e in reader ]
print(data)
```

printすると、2次元リストに格納されていることが確認できます。

```
[['city', 'code'], ['札幌市', '016010'], ['青森市', '020010'], ['盛岡市', '030010'], ['仙台市', '040010'], ['秋田市', '050010'], ['山形市', '060010'], ['福島市', '070010'], ['水戸市', '080010'], ['宇都宮市', '090010'], ['前橋市', '100010'], ['さいたま市', '110010'], ['千葉市', '120010'], ['東京', '130010'], ['横浜市', '140010'], ['新潟市', '150010'], ['富山市', '160010'], ['金沢市', '170010'], ['福井市', '180010'], ['甲府市', '190010'], ['長野市', '200010'], ['岐阜市', '210010'], ['静岡市', '220010'], ['名古屋市', '230010'], ['津市', '240010'], ['大津市', '250010'], ['京都市', '260010'], ['大阪市', '270000'], ['神戸市', '280010'], ['奈良市', '290010'], ['和歌山市', '300010'], ['鳥取市', '310010'], ['松江市', '320010'], ['岡山市', '330010'], ['広島市', '340010'], ['山口市', '350010'], ['徳島市', '360010'], ['高松市', '370010'], ['松山市', '380010'], ['高知市', '390010'], ['福岡市', '400010'], ['佐賀市', '410010'], ['長崎市', '420010'], ['熊本市', '430010'], ['大分市', '440010'], ['宮崎市', '450010'], ['鹿児島市', '460010'], ['那覇市', '470010']]
```

#都市名の入力
次に、input関数で、検索したい都市コードを入力します。
入力した都市名は変数「city_name」に代入します。

※実際はIDEに直接入力するのではなく、他のツールで入力されたものを値として持ってきますので、あくまでプログラム作成用の暫定的なものです。

```.py
#都市名を入力する
city_name = input(str('都市名入力：'))
```

#リストの検索
続いて、リスト（data）の中から入力した都市名と一致するものを検索します。

リストを上から舐めていって、は変数「city_name」に代入された都市名と一致したら検索を終了（break）するようにします。

```.py
#リスト（data）の中から入力した都市名と一致するものを検索する
for i in data:
    if city_name in i:
        result = True
        break
result
print(i)
```
「仙台市」を検索した場合、iの値は`['仙台市', '040010']`と出力されます。

※なお、この検索方法では、一致するものを発見した時点で検索を中断しますので、リストの中から複数検索したい場合は適していません。


#インデックス（何番目か？）の取得
やりたいことは都市名から都市No.を取得することなので、それには検索した都市の情報が何番目に格納されているか？を取得します。
そこで、iの値（`['仙台市', '040010']`）が何番目に格納されているかを、index()メソッドで取得します。

```.py
#一致したものがリスト（data）の何番目かを調べる
j = data.index(i)
print(j)
```
「仙台市」は、`4`番目（4行目）と取得できます。

#都市コードの場所の指定
これで「仙台市」は、`4`番目（4行目）ということがわかりましたので、仙台市の都市No.はリスト（data）の4行目の1列目（data[4][1]）に格納されていることが把握できました。
※pythonのリストは0番（0行・0列）から始まるため、ExcelのB5セルは、リストでは（data[4][1]）となります。

場所を指定して、都市No.が出力されることを確認してみましょう。

```.py
#該当行の1列目が都市コード
city_no = data[j][1]
#print(city_no)
```
都市No.（city_no）の値は`040010`と出力されます。



#サンプルプログラムコード

下記がこれまでの一連のコードをまとめたものです。
print()はコメントアウトしていますので、必要に応じて外してください。

```.py
import csv

#都市リスト（citylist.csv）を読み込んで、リスト（data）に格納する。   
f = open("citylist.csv","r",encoding="SHIFT-JIS")
reader = csv.reader(f)
data = [ e for e in reader ]
#print(data)

#都市名を入力する
city_name = input(str('都市名入力：'))

#リスト（data）の中から入力した都市名と一致するものを検索する
for i in data:
    if city_name in i:
        result = True
        break
result
#print(i)

#一致したものがリスト（data）の何行目かを調べる
j = data.index(i)
#print(j)

#都市コードの場所の指定（該当行の1列目が都市コード）
city_no = data[j][1]
#print(city_no)
```

#最後に
「指定した都市の天気予報をLivedoor天気から取得する」は、次回（現在、未投稿）の記事で書きたいと思います。