introduction
競技プログラミングの問題を解いていた際に用いた方法について書いていきます。
リストの任意の部分を取り出す処理について記述します。
誤っているところがあればコメント等よろしくお願いします。
リストの代入操作について理解が甘かったので、修正いたしました。リストが変数の場合は変数にリストオブジェクトのアドレス値が代入されているので、代入を行う際にはリストオブジェクトのアドレス値を渡しているという理解ができていませんでした。その点を主に修正しました。失礼いたしました。(2020/05/26)
リストの準備
下記で任意の2次元リストをnumpyを用いて作成しました。
import numpy as np
array=np.arange(16).reshape((4,4)) #データを準備
>>>array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
リストの任意部分を取り出す処理
例えば下記に示すような任意の赤丸で囲ったリストを取り出したいとき

pythonで実装すると以下のようにできると考えました。
div_array=[]
for i in range(1,3):
tep_array=[]
for j in range(1,3):
tep_array.append(array[i][j])
div_array.append(tep_array)
print(div_array)
# div_array=[[5, 6], [9, 10]]
ただ、この方法だと記述量も多く、変数をたくさん置く必要があって読みにくいです。
追記:arrayとdiv_arrayが示すリストオブジェクトは異なり、またそれぞれのリスト内のリストのアドレス値も異なっているので、どちらかのリスト内を変更した際にも独立に変更できます。
この読みにくさを解決するために、ndarray型配列であれば、スライスを用いることで実装できます。
(ただしpython のlistでlist[1:3,1:3]と指定するとエラーがおきます。)
div_array=array[1:3,1:3]
>>>div_array([[ 5, 6],
[ 9, 10]])
まず、左側の1:3で行方向を取りだし、
[ 4, 5, 6, 7] と[ 8, 9, 10, 11]の行を取り出します。
次に、右側の1:3で列方向を取り出せます。
よって、[5,6] と[9,10] が取り出せます。
ただ、この場合div_array内のリストのアドレスととarray内のリストのアドレスは同じなので、div_array内をを操作するとarray内のリストの値も変更してしまいます。そこでdiv_array内にarray内のリストとは異なる新たなリストを作成し、そのオブジェクトに元のリストの値をコピーする必要があります。その実装は
div_array=array[1:3,1:3].copy()
と記述することで解決できます。
追記:list内listをprint()するときの豆知識
話が少し逸れますが、list内の要素を順番に出力する際には
以下のようにすることが多いと思います。
for i in div_array:
print(i)
# [5 6]
# [ 9 10]
ただしlistの[]が表示されていると不正解になることもあり、これを防ぐために以下のように実装を試みました。
引数の end="" にスペースを指定し、5と6 をスペースで分割してその後の空のprint()で次の行に移ることを試みました。
for i in div_array:
for j in i:
print(j ,end=" ")
print()
>>>5 6 #6、10の後にスペースが入っている
>>>9 10 #6、10の後にスペースが入っている
ですが、この実装では6と10の後にもスペースが入ってしまい不正解となりました。
これを解決するために以下のようにすれば、簡単に解決することができました。
[ ]を外したいリストの前に*をつけて出力することによって、リスト内リストの各要素を分割して表示することができました。
for i in div_array:
print(*i)
>>>5 6
>>>9 10
まとめ
今回は2次元リストから任意のリストを取り出す方法と、2次元リストの出力のことに関して述べました。
かなりマニアックな内容ですが使ってみてください。