配列・文字列スライス操作

pythonでよく使う配列のスライス操作の確認

pythonを勉強し始めてからすごくスライス操作を使うので、ここで一度自分の確認のためにもまとめたいと思います。

配列の操作

まずは配列から、pythonでは作った配列に自動的に番号がつくようになっていて(indexと呼びます)0からスタートして作った中身の数分番号が振り当てられます。

l = [5,3,1,2]
print(l.index(5))
print(l.index(3))
print(l.index(1))
print(l.index(2))
$ python atcoder.py
0
1
2
3

こんな感じに配列の中の5,3,1,2には0123が順番に振られていることがわかりました。 ちなみにl.index()の.index()は配列などindexがふられているものに使える関数で、指定したところのindex番号が取れます。

次はそのインデックスを使って配列の値を取り出します。

l = [5,3,2,1]

print(l[0])
print(l[2])
$ python atcoder.py
5
2

こんな感じに配列に[]をつけてその中に取り出したいインデックスを指定します。 l[0]とすると0番目の5が取れます。

次は一つではなく複数の配列の中身をとります。

l = [5,3,2,1]
print(l[0:2])
$ python atcoder.py
[5, 3]

複数の値を取りたい時はみてわかるように[インデックス:インデックス]として、 はじめに指定した番号のところから後に指定した番号の範囲までを取得できます。 注意して欲しいのがfor文などと一緒で[0:2]とした場合2の一つ前つまりこの場合は0から1までの値を取得するようになっています。

次は最初からあるところまでや、あるところから最後までの方法

l = [5,3,2,1]
print(l[1:])
$ python atcoder.py
[3, 2, 1]
l = [5,3,2,1]
print(l[:3])
$ python atcoder.py
[5, 3, 2]

最初の方は[インデックス:]で指定したインデックスから最後までの値を取り出します 後の方は[:インデックス]で最初から指定したインデックスまで、後の方は先ほど説明したように一個手前までです。

応用

こんなことは日常にないかもしれませんが適当に数字が横に並んでいてどこで分けると一番左と右の大きさの差が少なくなるのか?みたいな時にはスライス操作が便利です。

l = [3,14,6,40,2,6,17,4,6,7,38,5,44,22,1,6,6,7]

for i in range(1,len(l)):
    l_l = l[:i]
    print(f"l_l{l_l}")
    l_r = l[i:]
    print(f"l_r{l_r}")

ある番号までと、ある番号からっていうある番号の値をひとつずつ増やしていくことで、右と左に全ての位置で分けられます。 rangeが1からなのは0からにすると一番初めのループでのl_lがl[:0]となり空の配列が出来上がり空とそのほかというのは比べる必要がにないのでそうしました。

l_l[3]
l_r[14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14]
l_r[6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6]
l_r[40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40]
l_r[2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2]
l_r[6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6]
l_r[17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17]
l_r[4, 6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4]
l_r[6, 7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6]
l_r[7, 38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7]
l_r[38, 5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38]
l_r[5, 44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5]
l_r[44, 22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44]
l_r[22, 1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22]
l_r[1, 6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1]
l_r[6, 6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6]
l_r[6, 7]
l_l[3, 14, 6, 40, 2, 6, 17, 4, 6, 7, 38, 5, 44, 22, 1, 6, 6]
l_r[7]

でここから全ての差を取ればいいですね、今回の記事には関係ないですが一応書きます

l = [3,14,6,40,2,6,17,4,6,7,38,5,44,22,1,6,6,7]

min_g = 10000000
ans = 0
for i in range(len(l)):
    l_l = l[:i]
    l_r = l[i:]

    if min_g > abs(sum(l_l)-sum(l_r)):
        min_g = abs(sum(l_l)-sum(l_r))
        ans = i

print(ans)
$ python atcoder.py
10

インデックス番号が10番目までと10番目からで分ける方法が一番差がないらしいです。

まとめ

まだまだスライスにはたくさんあって全部書くのは大変なので基本ですごく使うものを書きました。