「アウトプットと言う名の備忘録@Texas」

日本じゃない何処かの脳筋パイソニスタによる何かしらの走り書き

【Codingインタビュー対策】Python で文字列あれこれ!〜自責の念を込めて〜

お久しぶりです。

ここのところ転職活動に注力していた脳筋ニシキですが、
ありがたいことに

アメリカはテキサス州にある、とあるテック企業から

内定をいただくことができました!

ありがとうございます!!

今回はCoding インタビューで出題された

Python での String 操作

について少し自責の念を込めて触れていきたいと思います。

Coding インタビュー対策は日々 HackerRank で問題を解きまくっていたので

「まぁいけるっしょ!」

と完全になめてかかってたのですが、
いざ本番になってみると、細かい部分がさっと思い出せなかったり、ググっていいのかよくわからなかったり(普通に聞けばよかった)、そんなこんなで時間がみるみる過ぎていくという散々な結果に繋がってしまったのですが、幸いにも、今回のインタビューでは思考法やどう問題にアプローチするかに重きが置かれていたようで、ギリなんとかなりました

ただ、やはり悔しい!

ゆうても基礎中の基礎とも言える 文字列操作。これは瞬発的に回答できるようになりたい!
という事で
公式ドキュメントを参考に
復習タイムです。
f:id:At_sashimi_py:20191117112122p:plain

対象者

  • Python 初心者
  • 初めてのCoding インタビューを控えてる方
  • 文字列操作の基本を抑えたい方

環境

MacBook Pro (macOS Mojave)
Python 3.7

それでは見ていきましょう!
(間違えている点や、こっちの方がいいよーなどのアドバイスなどがありましたらお手数ですが、コメントしていただけると幸いかつ私の勉強になります!)

置換:str.replace(old, new, count)

文字列からoldを探しnewと置換します。
countの部分はオプションで、指定した数字分だけ頭から置換します。


では次の例題を見てみましょう。

例題

"I would like to eat sushi"
のように与えられた文字列の
"半角スペース"

"-"
を入れ替えて
"I-would-like-to-eat-sushi"
のような文字列を返そう。

解答例

def replace_ex(givne_string):
    new_string=givne_string.replace(' ','-')
    return new_string

print(replace_ex('I would like to eat sushi'))

#I-would-like-to-eat-sushi

解答例の解説

問題文そのままでreplace()を使って、
半角スペースを第一引数にとり、
第二引数に”-”を代入し、
半角スペースと”-”を取り替える。以上。

検索:str.find(sub, start, end)

文字列に sub が含まれる場合、その sub の一文字目の index を返します。オプション引数 start および end はスライス表記と同様に解釈されます。 sub が見つからなかった場合 -1 を返します。

公式のドキュメントにも書かれていますが、sub が部分文字列であるかどうかのみ知りたい場合は以下のように "in 演算子" を使いましょう。

>>> 'Py' in 'Python'
True

では次の例題を見てみましょう。

例題1

"afaweasfsushias" のように与えられた文字列に"sushi" というsubstring が含まれていた場合、最初の index をPrint せよ。
1つも含まれていない場合は "No" をPrint せよ。

解答例

def find_ex(givne_string, sub_string):
    index = givne_string.find(sub_string)
    if index != -1:
        print(index)
    else:
        print("No")
    return

givne_string = "sushifasfareasushifasushisuhisushi"
sub_string = "sushi"


find_ex(givne_string, sub_string)
#7

givne_string = "sushifasfareasushifasushisuhisushi"
sub_string = "sashimi"

find_ex(givne_string, sub_string)
#No

解答例の解説

if文を使ってfind() で返した index が -1 (つまりsubが文字列内に存在しない)ではないとき、index をPrint し、それ以外では "No" を吐きだします。

例題2

"afaweasfsushias" のように与えられた文字列に"sushi" というsubstring が含まれていた場合、全てのindex を Print せよ。
1つも含まれていない場合は "No" を Print せよ。

解答例

def find_multiple(givne_string, sub_string):
    index = givne_string.find(sub_string)
    if index != -1:
        index = 0
        while index != -1:
            index = givne_string.find(sub_string, index)
            if index != -1:
                print(index)
                index += 1
    else:
        print("No")
    return

sub_string="tomato"
find_multiple(givne_string, sub_string)

#No

sub_string="sushi"
find_multiple(givne_string, sub_string)

#7
#14
#23

解答例の解説

例題1と同様にif文を使っていきます。
Point は while ループを使ってsub が文字列内に存在し続ける限り index を1ずつ増加させながら回し続ける点。

分割:str.split(sep=None, maxsplit=-1)

文字列を第一引数の sep で区切った文字列のリストを返します。オプション引数のmaxsplit を指定すると maxsplit 回分割されます。 maxsplit を指定しない,もしくは -1 に設定すると全ての sep で分割されます。

兎にも角にも使ってみましょう。

例題

与えられた英文から単語の出現回数順に並べたリストを返す関数"common_words" を完成させよう。(与えられる英文の単語間は半角スペースとする。)

特に意味はないですがシェイクスピアの名言をここでは使わせていただきます。

'A fool thinks himself to be wise, but a wise man knows himself to be a fool'
『愚者は己が賢いと考えるが、賢者は己が愚かなことを知っている』

な、なるほど。。
ちなみに出現回数が同じものに関しての並びについては、ここでは気にしません。

解答例

from collections import Counter

def common_words(shakespeare_words):
    words_list = shakespeare_words.lower().split(' ')
    c = Counter(words_list).most_common()
    common_list = [i[0] for i in c]

    return common_list

shakespeare_words = 'A fool thinks himself to be wise, but a wise man knows himself to be a fool'
print(common_words(shakespeare_words))

#['a', 'fool', 'himself', 'to', 'be', 'thinks', 'wise,', 'but', 'wise', 'man', 'knows']

解答例の解説

  1. split(' ') で単語ごとに区切り、大文字小文字の区別をなくすため全て小文字にしつつリスト化。
  2. Counterでリストの各単語の出現個数をカウント。
  3. Counter の most_common() で、(単語, 出現回数)という形のタプルを出現回数順に並べたリストを取得。
  4. 欲しいのは単語だけのリストなのでリスト内包表記で取り出す。

連結:str.join() もしくは ”+ 演算子

str.join(iterable)

リストや、タプルを文字列に変換したい場合よく使います。

"iterable" にはリストや、タプルを、"str" の部分にはセパレーターを取り、"iterable" の内容をセパレーターで連結してた文字列を返します。

以下の例ではリストの中身を半角スペースで繋いで1つの文字列として
python is great” を Print out しています。

join_list = ["python", "is", "great"]

print(" ".join(join_list))

#python is great

演算子

”+ 演算子” はそのまま複数の文字列を繋げる役割を果たします。

例えばこんな感じで

a = "I "
b = "love "
c = "python!"

print(a + b + c)

#I love python!

例題

"I would like to eat sushi"
のように与えられた文字列の
"半角スペース"

"-"
を入れ替えて
"I-would-like-to-eat-sushi"
のような文字列を Print せよ。
ただし、replace() は使わずに。

上で扱った split() と join()で以下のようにしてみました。

解答例

def join_ex(givne_string):
    string_list = givne_string.split(' ')
    print('-'.join(string_list))
    return


join_ex('I would like to eat sushi')

#I-would-like-to-eat-sushi

解答例の解説

  1. 半角スペースで区切られた単語のリストをsplit()で作る。
  2. そしてjoin()で単語を"-"で連結。

任意文字または空白の削除:str.strip([chars])

読んで字の如く、文字列の外側(先頭&末尾)から引数 chars 値を剥ぎ取ったコピーを返します。引数 chars は除去される文字集合を指定する文字列です。
この剥ぎ取りは引数 chars の文字集合に含まれない文字に辿り着くまで続きます。何も指定しない場合は、外側から空白を剥ぎ取ります。

早速例題をみてみましょう。

例題

与えられた "ugly_list" から余計な"スペース"、"コンマ" 、"ピリオド"を取り除いた "clean_list" を Print せよ。

解答例

ugly_list = ['.   python.   ', '   .  javascript .    ', '...  .. swift,,,,']

clean_list = map(lambda x: x.strip(' ,.'), ugly_list)
print(list(clean_list))

解答例の解説

文字通り ugly_list からstrip()で余計な文字を先頭と末尾の両端から剥ぎ取る。

その他あれこれ

以前、文字列の大文字、小文字を操る capitalize() や、upper()lower()についても触れたので
よろしければそちらもご参照ください!
atsashimipy.hatenablog.com

参考リンク

docs.python.org
estorypost.com

以上、駆け足ですが Python での文字列操作をまとめさせていただきました!
これでまた、文字列操作を問われてもNo Google で即答できるのではないかと思います!多分笑

それでは皆様の良き Python Life を祈っております!!
また次回!
ありがとうございましたー!