しーなのたらたらプログラミング学習日記

よれたOLの、びみょーなプログラム学習日記です

Chapter12:文字列の分割:スライスとか zipとか

どうもどうもこんにちは!
プログラミングの内容について、毎日何か書こうと思っていたけど、
脳味噌がついていかなくって、苦戦してます、しーなです!

こういう記事って、ほんとは理解してないと書けないのね。 そいで、私はあんまり理解してないのに書こうとしているから蛇行するんですねー。
しかし、あれだよ!

きっと、書くことによって、思考が整理されるんだよ!きっとそう!
と、自分を励ましながら、今日もかきかきしているわけです。

さて、本日もお題に行ってみるよ。


Checkio 12:start スプリットペア
問題:文字列を 2 文字のペアに分割します。文字列に含まれる文字数が奇数の場合、最後のペアの 2 番目の欠落文字をアンダースコア ('_') に置き換える必要があります
x= list(split_pairs("abcd")) == ["ab", "cd"]
x= list(split_pairs("abc")) == ["ab", "c_"]
x= list(split_pairs("abcdf")) == ["ab", "cd", "f_"]
x= list(split_pairs("a")) == ["a_"]
x= list(split_pairs("")) == []
(↑半角だと見えなくなるので、例のアンダースコアは全角で記載してます)


解き方

  • スライスをどう使うかが問題・・・。
    この問題、答えにたどり着くのに一日くらいかかりましたが、苦し紛れで書いた、
    PASSするだけのためのコードでした。。。
    (のせるのはずかしいから、闇に葬った(*ノωノ))
  • 邪道かもですが、うまくその都度チェックする方法がみつけられなかったので、 最初に長さが奇数なら"_"をいれておくことにしちゃった!

・・・・しかし、考えてみると、
私ったらcheckioのサイトでこのレベルの回答を公開しちゃってたよね。


しかも、clear solutionくくりでw
(きゃーいま考えてみると全部消したい、ほんとはずかしい><)
*clear solution=明確で教育的な、わかりやすい答え


最初の解は捨てて、もっと素敵な方法を考えることにする!
ということで、最初から2回目の答え

def split_pairs(string):
   if len(string)%2!=0:
      string+="_"
   data=[string[i:i+2] for i in range(0,len(string),2)]
   return(data)

最初から2で割って余りが0じゃない時(奇数?)にアンダースコアをいれちゃえば、
あとは2個に切るだけ・・(ノ∀`) いえーい
自分としては、forを一列で書いたり、ちょっと頑張って何回も書き直して今の答えになったよ。

range関数の使い方については、言及したことなかったけど、
forを使う場合に、インデックスを使いたいときとかに使えるよ。


for i in range()


for i in range(100):
    print('パイソン大好き!')

これだと、0回めから100回?”パイソン大好き!"を出力するよ!

for i in range(3,10):
    print(i)
#3,4,5,6,7,8,9

始まりを3からはじめて9まで
(あれ、3から10までだと思っていた。だから時々思ったように動かなかったのねw)

for i in range(3,10,2):
    print(i)
#3,5,7,9

3始まりで2個飛ばしで9まで、みたいに使えるよ。
今回は、range(0,len(string),2)なので、 2飛ばしに、0から文字列の長さまで繰り返すって命令だよ!
ほんとは、len(string)みたいに書くと、よくないらしいので、
変数に置き換えた方がよいのかもしれないです。(そんな記事をどこかで読んだ)

さて、一応解けたので、 気になったほかの人のsolutionなんだけど

  return [c1+c2 for c1,c2 in zip(string[::2],string[1::2]+"_")]

これは正直、全然わからなかった・・・。

とりあえず、zip関数を調べてみよう。


zip:複数のイテラブルから、対応する要素をペアとしてまとめる


2つのリストとかをまとめて、タプルとして返してくれるらしい。

例: 2つのリストを結合してペアを作成する

 numbers = [1, 2, 3, 4, 5]
 letters = ['Are', 'Both', 'Come', 'Dream', 'Eye']

 comb= zip(numbers, letters)
 print(list(comb))
 >>[(1, 'Are'), (2, 'Both'), (3, 'Come'), (4, 'Dream'), (5, 'Eye')]

なるほど、便利な機能ですね。 しかしまてよ、さっきの解では何をzipしてるんだろう

  string=["abcdf"]
  a=zip(string[::2],string[1::2]+"_")
  for i in a:
    print(i)
    > ('a', 'b') #(2個飛ばしで最初、1番目から2個飛ばし)
    > ('c', 'd')
    > ('f', '_')

うーん・・・。 気になったので、分解して結果を出力してみたけど・・。

   data=[c1+c2 for c1,c2 in zip(string[::2],string[1::2]+"_")]

な、なるほど、zipした組み合わせがある間、両方を組み合わせるのか・・・。
文字列が2桁より多い場合は”_”はなんで切り捨てられるんだろうかとか、
やっぱり、じっくり眺めても、よくわからなかった・・・・。
(賢い人のコードって、難解だよね。。。。)

zip関数は、Mapやfilter関数なんかとよく組み合わされて使われるらしい 。

うーん、なんか自分では使いどころが難しそうな関数だな!
というのが正直な感想!そのうち使えるように一応メモを残しとこっと。