はじめに
pythonにはとっても便利な仕組みがあります。そのうちの一つがスライス。
どんなものかは例を見ればすぐわかります。
リスト操作
要素数10のリストの中から(先頭を0番目として)「2番目から4番目」を取り出したいときどうします?
わざわざfor文を回しますか? pythonではそんな必要はありません。
こうすればよいのです。
l=[10,9,8,7,6,5,4,3,2,1]
print(l[2:5]) #[8,7,6]
リスト名[始め:終わり]
と指定すると,リストの一部分を取り出せるわけです.
結果からわかるように、l[2:5]
と指定したとき2番目から3番目までしか取れていません。これは、このように考えると納得がいきます。
【0】10【1】9 【2】 8【3】7【4】6 【5】
間隔を指定する
また、奇数番目の要素だけ取り出したいとき、つまり1番目から一つ飛ばしで取り出したいときはこのようにします。
l=[10,9,8,7,6,5,4,3,2,1]
print(l[1:10:2]) #[9,7,5,3,1]
今度はリスト名[始め:終わり:間隔]
としました.間隔は省略可能で、その場合1がデフォルトの値として扱われます。
なお、始めと終わりも同様に省略ができ、例えば[:]
は[0:len(l)]
を意味します。これはつまり元のリストと等しいですね。
負の値も指定可能
また、これらに負の値を設定することも可能です。
l[-2:]
の結果はこのようになります。
l=[10,9,8,7,6,5,4,3,2,1]
print(l[-2:]) #[2,1]
「終わりから数えて2番目」から最後までが取り出されました.以下のように考えることが出来ます.
【-5】5【-4】4【-3】3 【-2】 2【-1】1
また,間隔に-1を指定すると,逆からリストを取り出せます(順序が逆転するということです).
ちなみに同様の操作はリスト名.reverse()
でも可能です.
l=[10,9,8,7,6,5,4,3,2,1]
print(l[::-1]) #[1,2,3,4,5,6,7,8,9,10]
文字列操作
さて、この「始め:終わり:間隔」の考え方は他の場面でも使えます。
文字列は,リストと同じように扱うことが出来ます.(ただし文字列は変更不可なので注意)
どういうことかというと、文字列のある一部分を取り出したいときにも、「始め:終わり:間隔」のスライスが使えるということです。
s='abcdefg'
print(s[2:6]) #'cdef'
#変数に入れなくても同じように扱える
print('abcdefg'[2:6]) #'cdef'
文字列に新たな文字を挿入/置換する
スライスを使うと,本来変更不可な文字列に新たに文字を挿入することが出来ます.
要は入れたい位置で文字列を二分割して,その間に文字を挿入してから再びくっつければよいのです.
少し変えると挿入ではなく任意の位置の文字を置換できます.
#0から数えて5番目の後に挿入
def insert_str(s, c, idx):
return s[:idx] + c + s[idx:]
#0から数えて5番目を置換
def replace_str(s, c, idx):
return s[:idx] + c + s[idx+1:]
s='123456'
print(insert_str(s, 'A', 2)) #'123A456'
print(replace_str(s, 'A', 2)) #'12A456'
range
厳密にはスライスと呼ばれるものではないと思うのですが、「始め:終わり:間隔」の考え方は同じなので取り上げます。
for文を回す時,しばしばrangeを用います.
s=''
for i in range(5):
s += str(i)
print(s) #'01234'
このrangeは コンマ区切りで 始めと終わりと間隔を指定できます.
s=''
for i in range(1,10,2):
s += str(i)
print(s) #'13579'
ただし,range(1,,2)
などはエラーになるので注意が必要です.
おまけ:enumerate
rangeを取り上げたのでどうせならenumerateも紹介しておきます.
もはやスライスでも何でもないのですが.
リスト内の全要素に順番にアクセスするとき,indexも同時に取得したい時に使います.
for文を書く際,リストをenumerateで包むだけです.
第二引数に数字を指定すると,indexがどの数字で始まるかを指定できます.全要素を取得することに変わりはありません.
l=['a','b','c','d']
#index,value
for index, name in enumerate(l):
print(index, name)
'''
0 a
1 b
2 c
3 d
'''
#第二引数は,indexをどの数字から始めるか指定する(全要素を取得すること自体は変わらない) 省略すると0
for index, name in enumerate(l,1):
print(index, name)
'''
1 a
2 b
3 c
4 d
'''
おわりに
スライス操作は非常に強力です.ぜひマスターしましょう.