programing

Python - 두 문자열 간의 차이

golfzon 2023. 5. 4. 20:50
반응형

Python - 두 문자열 간의 차이

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

이를 위해 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

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] != ' ']

정규식 모듈(퍼지 섹션)을 조사할 수 있습니다.실제 차이를 얻을 수 있을지는 모르겠지만 적어도 삽입, 삭제 및 대체와 같은 다양한 유형의 변경 허용 횟수를 지정할 수 있습니다.

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'

당신이 요구하는 것은 압축의 특수한 형태입니다.xdelta3는 이러한 종류의 압축을 위해 설계되었으며, 이를 위한 파이썬 바인딩이 있지만 zlib를 직접 사용하면 문제를 해결할 수 있습니다.사용할 수 있습니다.zlib.compressobj그리고.zlib.decompressobj와 함께zdict매개 변수를 "기본 단어"로 설정합니다. 예:afrykanerskojęzyczny.

주의사항은zdictPython 3.3 이상에서만 지원되며, 원하는 것과 다를 수 있는 모든 diff에 대해 동일한 "기본 단어"가 있으면 코드화하는 것이 가장 쉽습니다.

NLTK 라이브러리에서 사용할 수 있는 도구는 여러 단어 간의 차이를 계산하는 데 유용할 수 있습니다.

nltk.metrics.distance.edit_distance()Levenshtein 거리를 계산하는 성숙한(비표준) 라이브러리 구현입니다.

간단한 예는 다음과 같습니다.

from nltk.metrics.distance import *

w1 = 'wordone'
w2 = 'wordtwo'
edit_distance(w1, w2)

Out: 3

추가 매개 변수를 사용하면 다양한 작업(대체/삽입) 및 다양한 문자 차이(예: 키보드에 가까운 문자에 대한 비용 절감)에 따라 출력에 가중치를 부여할 수 있습니다.

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

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

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

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

당신이 해야 할 일은 단어 목록을 변경해야 하는 곳에 이 코드를 넣고, 변경해야 하는 단어를 단어 목록에 저장하고, 원래 단어가 올바른지 확인하는 것입니다.

저는 이 문제가 흥미로웠고 비록 이것이 오래된 질문일지라도 외부 라이브러리 없이 해결책을 개발해보고 싶었습니다.

import pytest

@pytest.mark.parametrize(
    "s1,s2,expected",
    [
        ("", "", ["", ""]),
        ("a", "a", ["", ""]),
        ("a", "b", ["a", "b"]),
        ("ac", "bc", ["a", "b"]),
        ("ca", "cb", ["a", "b"]),
        ("this is a message", "this is b message", ["a", "b"]),
        ("this is a huge message", "this is b message", ["a huge", "b"]),
    ],
)
def test_string_diff(s1, s2, expected):
    assert string_diff(s1, s2) == expected


def string_diff(s1: str, s2: str) -> str:
    d1, d2 = [], []
    i1 = i2 = 0
    l1 = len(s1)
    l2 = len(s2)
    while True:
        if i1 >= len(s1) or i2 >= len(s2):
            d1.extend(s1[i1:])
            d2.extend(s2[i2:])
            break
        if s1[i1] != s2[i2]:
            e1 = l1 - i1
            e2 = l2 - i2
            if e1 > e2:
                d1.append(s1[i1])
                i2 -= 1
            elif e1 < e2:
                d2.append(s2[i2])
                i1 -= 1
            else:
                d1.append(s1[i1])
                d2.append(s2[i2])
        i1 += 1
        i2 += 1
    return ["".join(d1), "".join(d2)]

언급URL : https://stackoverflow.com/questions/17904097/python-difference-between-two-strings

반응형