파이썬-두 문자열의 차이점


90

목록에 많은 단어를 저장하고 싶습니다. 이 단어의 대부분은 매우 유사합니다. 예를 들어 나는 단어가 afrykanerskojęzyczny와 같은 단어의 많은 afrykanerskojęzycznym, afrykanerskojęzyczni, nieafrykanerskojęzyczni. 두 문자열의 차이를 찾고 첫 번째 문자열과 diff에서 두 번째 문자열을 복원하는 효과적인 (빠르고 작은 diff 크기 제공) 솔루션은 무엇입니까?


1
"첫 번째 문자열에서 두 번째 문자열을 복원하고 diff"
jrd1 jul.

2
나는 그가 "두 번째 줄을 첫 번째 줄과 동일하게 만드십시오"라는 뜻이라고 믿습니다.
엘리아스 Benevedes

1
@EliasBenevedes, 정확히 :).
user2626682 jul.

1
당신은 뭔가를 찾고 difflib있습니까? 그렇다면 예를 들어 stackoverflow.com/questions/774316/…을
torek

답변:


113

difflib 모듈에서 ndiff 를 사용 하여이를 수행 할 수 있습니다 . 한 문자열을 다른 문자열로 변환하는 데 필요한 모든 정보가 있습니다.

간단한 예 :

import difflib

cases=[('afrykanerskojęzyczny', 'afrykanerskojęzycznym'),
       ('afrykanerskojęzyczni', 'nieafrykanerskojęzyczni'),
       ('afrykanerskojęzycznym', 'afrykanerskojęzyczny'),
       ('nieafrykanerskojęzyczni', 'afrykanerskojęzyczni'),
       ('nieafrynerskojęzyczni', 'afrykanerskojzyczni'),
       ('abcdefg','xac')] 

for a,b in cases:     
    print('{} => {}'.format(a,b))  
    for i,s in enumerate(difflib.ndiff(a, b)):
        if s[0]==' ': continue
        elif s[0]=='-':
            print(u'Delete "{}" from position {}'.format(s[-1],i))
        elif s[0]=='+':
            print(u'Add "{}" to position {}'.format(s[-1],i))    
    print()      

인쇄물:

afrykanerskojęzyczny => afrykanerskojęzycznym
Add "m" to position 20

afrykanerskojęzyczni => nieafrykanerskojęzyczni
Add "n" to position 0
Add "i" to position 1
Add "e" to position 2

afrykanerskojęzycznym => afrykanerskojęzyczny
Delete "m" from position 20

nieafrykanerskojęzyczni => afrykanerskojęzyczni
Delete "n" from position 0
Delete "i" from position 1
Delete "e" from position 2

nieafrynerskojęzyczni => afrykanerskojzyczni
Delete "n" from position 0
Delete "i" from position 1
Delete "e" from position 2
Add "k" to position 7
Add "a" to position 8
Delete "ę" from position 16

abcdefg => xac
Add "x" to position 0
Delete "b" from position 2
Delete "d" from position 4
Delete "e" from position 5
Delete "f" from position 6
Delete "g" from position 7

14
+1 Python에는 유용한 모듈 이 너무 많습니다. 매일 새로운 것을 배우는 것 같습니다.
arshajii jul.

1
이것은 수동으로 차이를 단계별로 살펴 보는 것입니다. 두 문자열 사이의 다른 복원 물론, 훨씬 쉽게 difflib.restore
임마

감사! 그러나 이것이 메모리 효율적인지 확실하지 않습니다. list (difflib.ndiff ( "afrykanerskojęzyczny", "nieafrykanerskojęzyczny")) [ '+ n', '+ i', '+ e', 'a', 'f', 'r', 'y', 'k' , 'a', 'n', 'e', ​​'r', 's', 'k', 'o', 'j', 'ę', 'z', 'y', 'c', ' z ','n ','y ']
user2626682

ndiff생성기이므로 메모리 효율성이 높습니다. list개별적으로 생성 된 문자 비교를 전체 목록으로 바꾸는 호출 입니다. 호출하지 않으면 한 번에 몇 개만 기억할 list수 있습니다.
dawg jul.

1
Python 2에서도 작동합니다 (나를 위해) 특정 소스와 특정 출력으로 질문하는 것이 좋습니다. 코멘트에서 디버깅 할 수 없습니다 ...
dawg

26

나는 ndiff 대답을 좋아하지만 모든 것을 변경 사항 목록에 모두 넣고 싶다면 다음과 같이 할 수 있습니다.

import difflib

case_a = 'afrykbnerskojęzyczny'
case_b = 'afrykanerskojęzycznym'

output_list = [li for li in difflib.ndiff(case_a, case_b) if li[0] != ' ']

3
이것은 내가 인터넷 검색을 한 것입니다. @Eric, 오늘 20180905와 같이 변수가 일치하지 않습니다. 1) 마지막 줄을로 output_list = [li for li in list(difflib.ndiff(case_a,case_b)) if li[0] != ' ']변경하거나 2) 문자열 변수의 이름을 case_a -> a및 로 변경하십시오 case_b -> b. 건배!
bballdave025

4
명령의 출력을 표시하는 것도 도움이 될 수 있습니다. >>> output_list; # result #['- b', '+ a', '+ m']
bballdave025

2
if not li.startswith(' ')의 eqivalent입니다 if li[0] != ' '일부는 더 명료 찾을 수 있습니다. 또는 심지어if item.startswith(('-', '+', ))
dmmfll aug

@DMfll Downvote. 나열하지 않아도 startswith()파이썬으로3.7.4
나단

3

regex 모듈 (퍼지 섹션)을 살펴볼 수 있습니다 . 실제 차이를 얻을 수 있는지는 모르겠지만 적어도 삽입, 삭제 및 대체와 같은 허용되는 변경 유형의 수를 지정할 수 있습니다.

import regex
sequence = 'afrykanerskojezyczny'
queries = [ 'afrykanerskojezycznym', 'afrykanerskojezyczni', 
            'nieafrykanerskojezyczni' ]
for q in queries:
    m = regex.search(r'(%s){e<=2}'%q, sequence)
    print 'match' if m else 'nomatch'

3

당신이 요구하는 것은 압축의 특수한 형태입니다. xdelta3 는 이러한 특정 유형의 압축을 위해 설계되었으며 이에 대한 파이썬 바인딩이 있지만 zlib를 직접 사용하는 것은 피할 수 있습니다. 예를 들어 "기본 단어"로 설정된 매개 변수 zlib.compressobjzlib.decompressobj함께 사용하고 싶을 것 입니다.zdictafrykanerskojęzyczny

주의 사항은 zdictpython 3.3 이상에서만 지원되며, 모든 diff에 대해 동일한 "기본 단어"가있는 경우 코딩하는 것이 가장 쉽습니다.


-2

원래 질문에 대한 위의 의견에 대한 답변은 이것이 그가 원하는 전부라고 생각하게 만듭니다.

loopnum = 0
word = 'afrykanerskojęzyczny'
wordlist = ['afrykanerskojęzycznym','afrykanerskojęzyczni','nieafrykanerskojęzyczni']
for i in wordlist:
    wordlist[loopnum] = word
    loopnum += 1

이렇게하면 다음이 수행됩니다.

단어 목록의 모든 값에 대해 단어 목록의 해당 값을 원래 코드로 설정합니다.

단어 목록을 변경해야하는 곳에이 코드를 놓고 단어 목록에 변경해야하는 단어를 저장하고 원래 단어가 올바른지 확인하기 만하면됩니다.

도움이 되었기를 바랍니다!


감사합니다.하지만 실제로는 'afrykanerskojęzyczny'와 유사성을 사용하여 'nieafrykanerskojęzyczni'와 같은 단어를 메모리 효율적인 방식으로 저장하고 싶습니다.
user2626682 jul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.