質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

3797閲覧

Python3 長さが同じ文字列同士の比較で違いが何個あるか

opyon

総合スコア1009

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

2クリップ

投稿2018/10/01 11:38

編集2018/10/01 12:14

####やりたいこと
長さが同じ文字列同士の比較で違いが何個あるかを調べる効率的な方法を模索しています。
現状は愚直にfor文でループさせて1文字づつ比較しています。
何か別の方法で比較出来るやり方あればご教示頂ければと思います。
####試したこと
検索したキーワード:文字列 比較 差分 違い 
似たような質問の回答からcollectionsやCounterが使えないかと思ったのですが何文字目かの比較が必要なので断念しました。

Python3

1def count_diff(q,a): 2 lst_q = list(q) 3 lst_a = list(a) 4 len_q = len(lst_q) 5 ng = 0 6 for i in range(len_q): 7 if lst_q[i] != lst_a[i]: 8 ng += 1 9 print('NG:',ng,q,a) 10 11q = 'abcdefg' 12a = 'abcdefg' 13b = 'xbcdefg' 14c = 'xbxdxfx' 15 16count_diff(q,a) 17count_diff(q,b) 18count_diff(q,c)
出力結果 NG: 0 abcdefg abcdefg NG: 1 abcdefg xbcdefg NG: 4 abcdefg xbxdxfx

回答頂いたコードの実行速度比較:GitHub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

この場合は、質問文のコードと同様に一文字ずつ処理すればそれで良いと思いますが……O(n)だし。アルゴリズム的な改善方法はないと思います(断言はできませんが)。

元のコードは無駄な処理が多く、オーバーヘッドが発生しているので、その分は改善できるでしょう。

python

1import timeit 2 3def count_diff1(q,a): 4 """ 5 オリジナル 6 """ 7 lst_q = list(q) 8 lst_a = list(a) 9 len_q = len(lst_q) 10 ng = 0 11 for i in range(len_q): 12 if lst_q[i] != lst_a[i]: 13 ng += 1 14 return ng 15 16def count_diff2(a,b): 17 """ 18 コードを単純化 19 """ 20 cnt = 0 21 for c1,c2 in zip(a, b): 22 if c1 != c2: 23 cnt += 1 24 return cnt 25 26 27q = 'abcdefg' 28a = 'abcdefg' 29b = 'xbcdefg' 30c = 'xbxdxfx' 31 32print(count_diff1(q,a)) 33print(count_diff2(q,a)) 34print(timeit.timeit(lambda: count_diff1(q,a))) 35print(timeit.timeit(lambda: count_diff2(q,a))) 36 37print(count_diff1(q,b)) 38print(count_diff2(q,b)) 39print(timeit.timeit(lambda: count_diff1(q,b))) 40print(timeit.timeit(lambda: count_diff2(q,b))) 41 42print(count_diff1(q,c)) 43print(count_diff2(q,c)) 44print(timeit.timeit(lambda: count_diff1(q,c))) 45print(timeit.timeit(lambda: count_diff2(q,c))) 46 47""" => 480 490 501.819975644000806 510.8293105610064231 521 531 541.9003565619932488 550.8559812610037625 564 574 582.127330388990231 590.9501454940182157 60"""

倍程度改善します。

投稿2018/10/01 11:49

編集2018/10/01 12:19
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/10/01 12:16

ありがとうございます。 実行速度計測して確認しました。 知らない書き方なので調べながらあれこれ試してみます。
opyon

2018/10/01 12:32

今更なのですがzip関数調べてみたら超便利でした。 今まで知らずに定型文として使ってたことありましたが盲点でした^^; 今後使えるところあれば積極的に使いたいと思います。
opyon

2018/10/01 12:54

もうひとつ今更で知らないことがありました。 for文で文字列変数をinで指定した時にループで回せるということです。 今まで毎回リストに変換してました(多分javaの癖だと思います)。 このような質問していいのか少し戸惑いながらでしたが派生的に他のことも知れてとても参考になりました。 ありがとうございました。
guest

0

とりあえず簡潔な書き方を考えます。

Python

1def count_diff2(q, a): 2 return sum( 3 c1 != c2 for c1, c2 in zip(q, a) 4 )

1文字ずつ比較しているのには変わりありませんが、
Pythonの機能に頼っている分、ほんの少しだけ実行効率が良いようです。

計測結果 (1000000回実行)

count_diff1 2.729970581829548 count_diff2 2.3848468139767647

計測用コード Wandbox

投稿2018/10/01 11:48

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2018/10/01 11:50

私もそれ試したら、遅かったので没にしました 無駄に0が加算されるので、ifの方が速いってことかなと
LouiS0616

2018/10/01 11:55

かもしれませんね。 sum(1 for c1, c2 in zip(q, a) if c1 != c2) にしたら少しだけ改善されました。 それでも hayataka2049 さんの count_diff2 にはかないませんが。 シンプルイズベストってことでしょうね。
opyon

2018/10/01 12:17

ありがとうございます。 処理速度はさほど変わらないのにスマートな書き方で勉強になります。
guest

0

解決済みですので、参考まで。

結局のところ、遅くなっている原因が繰り返し処理にあるだとすれば、numpyを使って一括処理しようというものです。

python

1import numpy as np 2 3ar_lst_q = np.array(lst_q) # arrayに変換 4ar_lst_a = np.array(lst_a) # arrayに変換 5diff = ar_lst_q != ar_lst_a # 配列を一括比較 -> 要素同士の比較結果が配列で格納される 6result = np.sum(diff)

上記は、ふたつの文字列が同じ長さだから可能なものです。長さが異なる場合は適用できません。

投稿2018/10/01 12:55

R.Shigemori

総合スコア3376

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/10/01 13:10

ありがとうございます。 恐らく環境的な問題でnumpy絡みのエラーが出ているので解決次第確認します。
hayataka2049

2018/10/01 14:17 編集

実測した感じ、100文字以上くらいならその方が速そうです ↑計測ミスがあったので訂正、かなり長い文字列でも素直にループした方が早かったです
R.Shigemori

2018/10/01 15:13

numpyって意外と遅いんですね。 じゃぁ、import cupy as npにしたら… って、それでは環境が違いすぎますね。
hayataka2049

2018/10/01 15:31

numpyが遅い速いというより、この手の文字列処理では恩恵を受けられないと言うだけの話な気がします あと素のpythonが意外と優秀なときは優秀
opyon

2018/10/01 17:00

https://gyazo.com/7de0225ffa5ff7b4248b91efb5c7cd58 numpyのエラーが解決してやっと検証出来ました。 今回の例では遅いようです。 使い所次第で良い結果が出ることもあるかもしれません。 numpyを使ったことがあまりないのでどのように使うかも今後の課題です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問