20

これは私が望む動作です:

a: IGADKYFHARGNYDAA
c: KGADKYFHARGNYEAA
2 difference(s).
4

12 に答える 12

18
def diff_letters(a,b):
    return sum ( a[i] != b[i] for i in range(len(a)) )
于 2012-09-01T10:15:38.780 に答える
13

この例は、Python ソフトウェア バージョンとの相互運用性の問題に悩まされることなく、特定のケースで機能すると思います (2.7 にアップグレードしてください)。

a='IGADKYFHARGNYDAA'
b='KGADKYFHARGNYEAA'

u=zip(a,b)
d=dict(u)

x=[]
for i,j in d.items(): 
    if i==j:
        x.append('*') 
    else: 
        x.append(j)
        
print x

出力: ['*', 'E', '*', '*', 'K', '*', '*', '*', '*', '*']


いくつかの微調整で、あなたが望むものを手に入れることができます....それが役立つかどうか教えてください:-)


アップデート

これを使用することもできます:

a='IGADKYFHARGNYDAA'
b='KGADKYFHARGNYEAA'

u=zip(a,b)
for i,j in u:
    if i==j:
        print i,'--',j
    else: 
        print i,'  ',j

出力:

I    K
G -- G
A -- A
D -- D
K -- K
Y -- Y
F -- F
H -- H
A -- A
R -- R
G -- G
N -- N
Y -- Y
D    E
A -- A
A -- A

更新 2

次のようにコードを変更できます。

y=[]
counter=0
for i,j in u:
    if i==j:
        print i,'--',j
    else: 
        y.append(j)
        print i,'  ',j
        
print '\n', y

print '\n Length = ',len(y)

出力:

I    K
G -- G
A -- A
D -- D
K -- K
Y -- Y
F -- F
H -- H
A -- A
R -- R
G -- G
N -- N
Y -- Y
D    E
A -- A
A    X

['K', 'E', 'X']

 Length =  3
于 2012-09-01T11:01:07.713 に答える
12

法則

  1. 両方の文字列を同時に反復し、文字を比較します。
  2. スペースバーまたは|文字をそれぞれ追加して、新しい文字列で結果を保存します。また、異なる文字ごとにゼロから始まる整数値を増やします。
  3. 結果を出力します。

実装

組み込みzip関数を使用するかitertools.izip、両方の文字列を同時に反復することができますが、後者は巨大な入力の場合に少しパフォーマンスが高くなります。文字列が同じサイズでない場合、反復は短い部分に対してのみ行われます。この場合、残りを不一致を示す文字で埋めることができます。

import itertools

def compare(string1, string2, no_match_c=' ', match_c='|'):
    if len(string2) < len(string1):
        string1, string2 = string2, string1
    result = ''
    n_diff = 0
    for c1, c2 in itertools.izip(string1, string2):
        if c1 == c2:
            result += match_c
        else:
            result += no_match_c
            n_diff += 1
    delta = len(string2) - len(string1)
    result += delta * no_match_c
    n_diff += delta
    return (result, n_diff)

上記の例とは少し異なるオプションを使用した簡単なテストを次に示します。結果の文字列がより長い文字列のサイズに拡張される方法をよりよく示すために、一致しない文字を示すためにアンダースコアを使用していることに注意してください。

def main():
    string1 = 'IGADKYFHARGNYDAA AWOOH'
    string2 = 'KGADKYFHARGNYEAA  W'
    result, n_diff = compare(string1, string2, no_match_c='_')

    print "%d difference(s)." % n_diff  
    print string1
    print result
    print string2

main()

出力:

niklas@saphire:~/Desktop$ python foo.py 
6 difference(s).
IGADKYFHARGNYDAA AWOOH
_||||||||||||_|||_|___
KGADKYFHARGNYEAA  W
于 2012-09-01T10:25:48.173 に答える
5

Python には優れたdifflibがあり、必要な機能を提供するはずです。

ドキュメントの使用例は次のとおりです。

import difflib  # Works for python >= 2.1

>>> s = difflib.SequenceMatcher(lambda x: x == " ",
...                     "private Thread currentThread;",
...                     "private volatile Thread currentThread;")
>>> for block in s.get_matching_blocks():
...     print "a[%d] and b[%d] match for %d elements" % block
a[0] and b[0] match for 8 elements
a[8] and b[17] match for 21 elements
a[29] and b[38] match for 0 elements    
于 2012-09-01T10:14:02.223 に答える
2
a = "IGADKYFHARGNYDAA" 
b = "KGADKYFHARGNYEAAXXX"
match_pattern = zip(a, b)                                 #give list of tuples (of letters at each index)
difference = sum (1 for e in zipped if e[0] != e[1])     #count tuples with non matching elements
difference = difference + abs(len(a) - len(b))            #in case the two string are of different lenght, we add the lenght difference
于 2016-11-17T11:19:11.407 に答える
0

Niklas R からの回答は気に入っていますが、問題があります (期待に応じて)。次の 2 つのテスト ケースで回答を使用します。

print compare('berry','peach')
print compare('berry','cherry')

チェリーはモモよりもベリーに似ていると期待するのは当然かもしれません。それでも、berrypeachの差が小さくなり、次にberrycherryの差が小さくなります。

(' |   ', 4)  # berry, peach
('   |  ', 5) # berry, cherry

これは、文字列が順方向よりも逆方向に似ている場合に発生します。Niklas R からの回答から回答を拡張するために、通常の (前方) 差分と逆文字列の差分との間の最小差分を返すヘルパー関数を追加できます。

def fuzzy_compare(string1, string2):
    (fwd_result, fwd_diff) = compare(string1, string2)
    (rev_result, rev_diff) = compare(string1[::-1], string2[::-1])
    diff = min(fwd_diff, rev_diff)
    return diff

次のテスト ケースを再度使用します。

print fuzzy_compare('berry','peach')
print fuzzy_compare('berry','cherry')

...そして、私たちは得ます

4 # berry, peach
2 # berry, cherry

私が言ったように、これはNiklas R からの答えを変更するのではなく、単に拡張するだけです.

単純な diff 関数を探しているだけの場合 (前述の落とし穴を考慮して)、次のようにします。

def diff(a, b):
    delta = do_diff(a, b)
    delta_rev = do_diff(a[::-1], b[::-1])
    return min(delta, delta_rev)

def do_diff(a,b):
    delta = 0
    i = 0
    while i < len(a) and i < len(b):
        delta += a[i] != b[i]
        i += 1
    delta += len(a[i:]) + len(b[i:])
    return delta

テストケース:

print diff('berry','peach')
print diff('berry','cherry')

最後に考慮すべき点は、異なる長さの単語を処理する場合の diff 関数自体です。次の 2 つのオプションがあります。

  1. 長さの違いを文字の違いと考えてください。
  2. 長さの違いを無視して、最も短い単語のみを比較します。

例えば:

  • すべての文字を考慮すると、 appleapplesの差は 1 です。
  • 最短の単語のみを考慮すると、appleapplesの差は 0 です

使用できる最短の単語のみを考慮する場合:

def do_diff_shortest(a,b):
    delta, i = 0, 0
    if len(a) > len(b):
        a, b = b, a
    for i in range(len(a)):
        delta += a[i] != b[i]
    return delta

...反復回数は最短の単語によって決定され、それ以外はすべて無視されます。または、さまざまな長さを考慮することができます。

def do_diff_both(a, b):
    delta, i = 0, 0
    while i < len(a) and i < len(b):
        delta += a[i] != b[i]
        i += 1
    delta += len(a[i:]) + len(b[i:])
    return delta

この例では、残りの文字がカウントされ、差分値に追加されます。両方の機能をテストするには

print do_diff_shortest('apple','apples')
print do_diff_both('apple','apples')

出力します:

0 # Ignore extra characters belonging to longest word.
1 # Consider extra characters.
于 2016-03-09T15:43:12.193 に答える