Pythonの便利技と注意点:リスト編

[目次に戻る](https://qiita.com/yuta-sanjyo/items/416b05f8498df1ed3f49)

# 文字列を簡単にListに入れる
```py:文字列をリストに変換すると一文字ずつ「''」で囲わなくて便利
>>> list('Hello')
['H', 'e', 'l', 'l', 'o']

>>> list('12345')
['1', '2', '3', '4', '5']
```
```py:文字列リストを本来の並びに戻したい場合はjoin
>>> l = list('Hello')
>>> l
['H', 'e', 'l', 'l', 'o']
>>> ''.join(l)
'Hello'
```

# リストの中にある文字列の場所を探す
```py:index()
>>> abc = ['a', 'b', 'c']
>>> abc.index('c')
2
```

# 変数に格納した数分のリストを初期化する
```py:数字0で初期化する
>>> list_len = int(input())
3
>>> zero_list = [0] * list_len
>>> zero_list
[0, 0, 0]
```
```py:文字'a'で初期化する
>>> list_len = int(input())
3
>>> a_list = ['a'] * list_len
>>> a_list
['a', 'a', 'a']
```

# 2次元の配列を初期化する技
```py:forを使って包括する方法
>>> init_val = 'a'
>>> li_col = 3
>>> li_row = 5
>>> new_lists = [[init_val for col in range(li_col)] for row in range(li_row)]
>>> print(new_lists)
[['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
```
```py:比較的簡単な方法
>>> a_list = [['a'] * 10, ['a'] * 10]
>>> print(a_list)
[['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']]

>>> a_list[0][3] = 'bbbbbb'
>>> print(a_list)
[['a', 'a', 'a', 'bbbbbb', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']]
```
```py:こうすると、2つ目の配列も同じ先を参照してしまうので注意
>>> a = [['a'] * 10] * 2
>>> print(a)
[['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']]

>>> a[0][2]= 'bbbbbb'
>>> print(a)
[['a', 'a', 'bbbbbb', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'bbbbbb', 'a', 'a', 'a', 'a', 'a', 'a', 'a']]
```

# リストに英大文字・小文字を一気に入れる
```py:string をインポートする
>>> import string

>>> upper_list = list(string.ascii_uppercase)
>>> print(upper_list)
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

>>> lower_list = list(string.ascii_lowercase)
>>> print(lower_list)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
```

# リストに数字を順番に入れる
```py:
>>> num_list = list(range(1, 10))
>>> print(num_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

# リストのソートのオプション
```py:文字列の長さ順にソートする
>>> str_len = ['abcdef', 'ab', 'abc', 'a', 'abcde']
>>> str_len.sort(key=len)
>>> str_len
['a', 'ab', 'abc', 'abcde', 'abcdef']
```
```py:逆順にソートする
>>> int_len = [3, 2, 9, 5, 1, 8, 4]
>>> int_len.sort(reverse=True)
>>> int_len
[9, 8, 5, 4, 3, 2, 1]
```

# 2次元配列にてlambaを使うと各要素の順番でソートしてくれる
```py:各要素の0番目→1番目→2番目の順番でソート
>>> a_list = [[3, 5, 8], [1, 2, 3], [3, 5, 9], [3, 6, 4]]
>>> sorted_list = sorted(a_list, key=lambda x:(x[0], x[1], x[2]))
>>> print(sorted_list)
[[1, 2, 3], [3, 5, 8], [3, 5, 9], [3, 6, 4]]
```
```py:各要素の1番目→2番目→0番目の順番でソート
>>> a_list = [[3, 9, 8], [5, 8, 3], [3, 1, 9], [3, 8, 4]]
>>> sorted_list = sorted(a_list, key=lambda x:(x[1], x[2], x[0]))
>>> print(sorted_list)
[[3, 1, 9], [5, 8, 3], [3, 8, 4], [3, 9, 8]]
```

# リストにリストをappendすると値ではなく参照値が追加される注意点
```py:1つ目のリスト4番目の値を変えたと思ったら2つ目のリストの4番目も変わってしまう
>>> a_list = []
>>> original_list = [1, 2, 3, 4, 5]
>>> a_list.append(original_list)
>>> print(a_list)
[[1, 2, 3, 4, 5]]

>>> a_list.append(original_list)
>>> print(a_list)
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]

>>> a_list[0][3] = 100
>>> print(a_list)
[[1, 2, 3, 100, 5], [1, 2, 3, 100, 5]]
```
```py:解決策の一つとしてはcopy()を使う
>>> original_list = [1, 2, 3, 4, 5]
>>> b_list = []
>>> b_list.append(original_list.copy())
>>> print(b_list)
[[1, 2, 3, 4, 5]]

>>> b_list.append(original_list.copy())
>>> print(b_list)
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]

>>> b_list[0][3] = 100
>>> print(b_list)
[[1, 2, 3, 100, 5], [1, 2, 3, 4, 5]]
```

# 元のリストを変更しないようにsort()を使う
```py:sort()は元のリストを変えてしまう
>>> x = [3, 1, 6, 2, 9]
>>> x.sort()
>>> x
[1, 2, 3, 6, 9]
```
```py:sort()したものを別の変数にコピーしてもNG
>>> x = [3, 1, 6, 2, 9]
>>> y = x.sort()
>>> print(y)
None
```
```py:解決法１：copy()してからsort()する
>>> x = [3, 1, 6, 2, 9]
>>> y = x.copy()
>>> y.sort()
>>> x
[3, 1, 6, 2, 9]
>>> y
[1, 2, 3, 6, 9]
```
```py:解決法２：sorted()を使う
>>> x = [3, 1, 6, 2, 9]
>>> y = sorted(x)
>>> x
[3, 1, 6, 2, 9]
>>> y
[1, 2, 3, 6, 9]
```

# リストの中にいくつあるか数える
```py:count()
>>> ['b', 'c', 'a', 'b', 'd'].count('b')
2
```

# リストの拡張extend()
```py:元のリスト.extend(追加するリスト)
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[4, 5, 6]
```

# zip()で2つのlistをドッキング
```py:タプルのシーケンスを返す
>>> menus = ['ハンバーガー', 'ポテト', 'オレンジジュース']
>>> prices = [300, 150, 100]
>>> list(zip(menus, prices))
[('ハンバーガー', 300), ('ポテト', 150), ('オレンジジュース', 100)]
```
```py:タプルをループさせてアンパックも可能
>>> for menu, price in zip(menus, prices):
	print(menu, 'は', price, '円です')

ハンバーガー は 300 円です
ポテト は 150 円です
オレンジジュース は 100 円です
```
```py:リストを辞書としてドッキング
>>> menu_list = {menu:price for menu, price in zip(menus, prices)}
>>> menu_list
{'ハンバーガー': 300, 'ポテト': 150, 'オレンジジュース': 100}
```


# リストのdel仕様
実は、Python には値を削除する方法がない。値が使われなくなるとインタプリタが自分で削除するから、自分でコーディングして削除する必要がない仕様となっている。

```py:参照渡しなので、コピー先のリストの要素を変えるとコピー元の要素も変えてしまう
>>> a = ["こんにちは", "みなさん"]
>>> b = a
>>> b[1] = "ごきげんいかがですか"
>>> a
['こんにちは', 'ごきげんいかがですか']
```
```py:ところが、コピー元を削除しても、コピー先は残っている
>>> del a
>>> b
['こんにちは', 'ごきげんいかがですか']
```

# map関数：リストの初期化を行う時に1行で数値・文字列を指定して格納する技
```py:通常input()で入力されたものは、全てstrで格納される
>>> str_list = list(input())
12345
>>> print(str_list)
['1', '2', '3', '4', '5']
```

```py:mapを使うとinput()で入力された文字列も1行で数値に変換して格納できる
>>> int_list = list(map(int, input()))
12345
>>> print(int_list)
[1, 2, 3, 4, 5]
```

```py:数値が格納されているリストも1行で文字に変更できる
>>> int_to_str_list = [1, 2, 3, 4, 5]
>>> print(int_to_str_list)
[1, 2, 3, 4, 5]

>>> int_to_str_list = list(map(str, int_to_str_list))
>>> print(int_to_str_list)
['1', '2', '3', '4', '5']
```

```py:文字が格納されているリストも1行で数値に変更できる
>>> str_to_int_list = ['1', '2', '3', '4', '5']
>>> print(str_to_int_list)
['1', '2', '3', '4', '5']

>>> str_to_int_list = list(map(int, str_to_int_list))
>>> print(str_to_int_list)
[1, 2, 3, 4, 5]
```

# list表示の技
```py:list名だけprintすると[ ]も一緒に表示される
>>> fruits = ['apple', 'grape', 'banana']
>>> print(fruits)
['apple', 'grape', 'banana']
```
```py:for文を使って一つずつ取り出すと[ ]無しで改行して表示する
>>> for fruit in fruits:
    	print(fruit)	
apple
grape
banana
```
```py: アスタリスク（*）を使うと1行・[ ]無し・スペース区切りで表示する
>>> print(*fruits)
apple grape banana
```
```py:リストの中身を逆順に表示するreversed()
>>> fruits_list = ['apple', 'grape', 'melon', 'lemon']
>>> for fruit in reversed(fruits_list):
	print(fruit)	
lemon
melon
grape
apple
```

# リストの中身を比較して共通個所を抜き出す
```py:setを使う
>>> li_a = ['a', 'b', 'c']
>>> li_b = ['b', 'c', 'd']
>>> common_str = set(li_a) & set(li_b)
>>> print(common_str)
{'b', 'c'}
```

# リストにあるkeyに対応する値を辞書からとってくる
```py:辞書.get(key)
>>> dic = {'A': 1, 'B':2, 'C':3, 'D':4}
>>> key_list = ['B', 'C', 'D', 'A']
>>> for key in key_list:
...     print(key, ':', dic.get(key))
... 
B : 2
C : 3
D : 4
A : 1
```

# リストの中が全て0か0以外かを判定するany()関数
```Py:1つでも0以外の値が入っているとTrueになり、全て0ならFalse
list_a = [0, 0, 1]
list_b = [0, 0, 0]

print(any(list_a))
print(any(list_b))
==================
# 出力結果
True
False
```

# 縦横同じ長さの構造体リストの中身を縦と斜めに並び替える
```Py:1から9までの数字が格納されている3x3の立方体を例とする
# 3x3の立方体作成
cube_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 縦に並べ替える時に一時的に格納するリスト
cube_parts = []

# 縦に並べ替える構造体リスト
cube_vertical = []

# 左上から右下への斜め要素を格納するリスト
cube_LRslash = []

# 右上から左下への斜め要素を格納するリスト
cube_RLslash = []

# 縦に並べるには2重ループのiとjをひっくり返す
# [1, 4, 7]
# [2, 5, 8]
# [3, 6, 9]
for i in range(3):
    cube_parts = []
    for j in range(3):
        cube_parts.append(cube_list[j][i])
    cube_vertical.append(cube_parts)

# 左上から右下への斜めにするには行と列のインデックスを同じにしてやればよい
# [1, 5, 9]
for i in range(3):
    cube_LRslash.append(cube_list[i][i])

# 右上から左下への斜めにするには
# 列数から1と行数を引いてやればよい
# [3, 5, 7]
for i in range(3):
    cube_RLslash.append(cube_list[i][3 - 1 - i])

print(cube_list)
print(cube_vertical)
print(cube_LRslash)
print(cube_RLslash)
=================================================
# 出力結果
# 元の構造体
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 縦に並べ替えた構造体
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

# 左上から右下への斜めラインを取り出したリスト
[1, 5, 9]

# 右上から左下への斜めラインを取り出したリスト
[3, 5, 7]
```

# リストの中の値を一定のところで折り返して表示する
例では、1から36までの数字が入ったリストを、6で折り返して6x6の立方体のように並べた。
なお、立方体になるように、数字の表示は{:0>2}でフォーマットしている。
ポイントは、最初のfor文で増分を折り返し文字数に設定して、次のfor文で折り返し始点から次の増分された折り返しまでをスライスして1つずつ取り出している箇所となる。
```Py:
all_list = list(range(1, 37))

return_num = 6
for i in range(0, len(all_list), return_num):
    for num in all_list[i:i+return_num]:
        if num % return_num != 0:
            print("{:0>2}".format(num), end=' ')
        elif num % return_num == 0:
            print("{:0>2}".format(num), end='\n')
=============================================
01 02 03 04 05 06
07 08 09 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
```

[目次に戻る](https://qiita.com/yuta-sanjyo/items/416b05f8498df1ed3f49)