Eu gostaria de armazenar muitas palavras em uma lista. Muitas dessas palavras são muito semelhantes. Por exemplo, eu tenho palavra afrykanerskojęzyczny
e muitos de palavras como afrykanerskojęzycznym
, afrykanerskojęzyczni
, nieafrykanerskojęzyczni
. Qual é a solução eficaz (rápida e com tamanho de diff pequeno) para encontrar a diferença entre duas strings e restaurar a segunda string da primeira e diff?
python
string
python-3.x
diff
user2626682
fonte
fonte
difflib
? Em caso afirmativo, consulte, por exemplo, stackoverflow.com/questions/774316/…Respostas:
Você pode usar o ndiff no módulo difflib para fazer isso. Ele contém todas as informações necessárias para converter uma string em outra.
Um exemplo simples:
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()
estampas:
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
fonte
ndiff
é um gerador, portanto, é bastante eficiente em termos de memória. Você está chamandolist
isso, o que transforma as comparações de caracteres geradas individualmente em uma lista completa deles. Você só teria alguns na memória de cada vez se não os chamasselist
.Eu gosto da resposta ndiff, mas se você quiser cuspir tudo em uma lista apenas das mudanças, você pode fazer algo como:
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] != ' ']
fonte
output_list = [li for li in list(difflib.ndiff(case_a,case_b)) if li[0] != ' ']
ou 2) mude os nomes das variáveis de string comocase_a -> a
ecase_b -> b
. Felicidades!>>> output_list
:; # resultado #['- b', '+ a', '+ m']
if not li.startswith(' ')
é o equivalente deif li[0] != ' '
Alguns podem achá-lo mais legível. Ou mesmoif item.startswith(('-', '+', ))
startswith()
partir de python3.7.4
Você pode olhar para o módulo regex (a seção fuzzy). Não sei se você pode obter as diferenças reais, mas pelo menos você pode especificar o número permitido de diferentes tipos de alterações, como inserir, excluir e substituições:
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'
fonte
O que você está pedindo é uma forma especializada de compressão. O xdelta3 foi projetado para esse tipo específico de compactação e há uma ligação python para ele, mas você provavelmente conseguiria usar o zlib diretamente. Você gostaria de usar
zlib.compressobj
ezlib.decompressobj
com ozdict
parâmetro definido para sua "palavra base", por exemploafrykanerskojęzyczny
.As advertências são
zdict
suportadas apenas no python 3.3 e superior, e é mais fácil codificar se você tiver a mesma "palavra base" para todos os seus diffs, que podem ou não ser o que você deseja.fonte
A resposta ao meu comentário acima sobre a questão original me faz pensar que isso é tudo que ele quer:
loopnum = 0 word = 'afrykanerskojęzyczny' wordlist = ['afrykanerskojęzycznym','afrykanerskojęzyczni','nieafrykanerskojęzyczni'] for i in wordlist: wordlist[loopnum] = word loopnum += 1
Isso fará o seguinte:
Para cada valor na lista de palavras, defina esse valor da lista de palavras como o código original.
Tudo o que você precisa fazer é colocar este trecho de código onde deseja alterar a lista de palavras, certificando-se de armazenar as palavras que deseja alterar na lista de palavras e de que a palavra original está correta.
Espero que isto ajude!
fonte