2011-12-17 19 views
9

Mam dwa ciągi o równej długości, jak mogę znaleźć wszystkie lokalizacje, w których ciągi są różne?Znaleźć pozycję różnicy między dwoma ciągami

Na przykład, „HELPMEPLZ” i „HELPNEPLX” różnią się w pozycjach 4 i 8.

+0

wygląda dla mnie jak zadanie domowe. pokaż, co próbowałeś i gdzie masz problemy, a następnie spróbuj zadać konkretne pytania. – tback

+0

To nie jest praca domowa, potrzebuję go do znacznie większego functioncomplex. Więc tutaj jest trochę trudno napisać wszystko. –

+0

Ale funkcje dzielą struny w górę: ("HEL", "PME", "PLZ") i ("HEL", "PNE", "PLX") –

Odpowiedz

2

Jeśli przechowywać dwa ciągi w a i b można pętli wszystkich elementów i sprawdzić nierówności.

interaktywny interpreter Pythona:

>>> for i in range(len(a)): 
... if a[i] != b[i]: print i, a[i], b[i] 
... 
4 M N 
8 Z X 

Innym sposobem na to jest z listowych. Wszystko w jednym wierszu, a wyjście to lista.

>>> [i for i in range(len(a)) if a[i] != b[i]] 
[4, 8] 

Dzięki temu bardzo łatwo jest zawinąć w funkcję, co ułatwia wywoływanie na różnych wejściach.

>>> def dif(a, b): 
...  return [i for i in range(len(a)) if a[i] != b[i]] 
... 
>>> dif('HELPMEPLZ', 'HELPNEPLX') 
[4, 8] 
>>> dif('stackoverflow', 'stacklavaflow') 
[5, 6, 7, 8] 
+0

Nie używaj lambdy, gdy nie musisz: 'def dif (a, b): return [i for i in range (len (a)) if a [!] = B [i]]' –

+0

@StevenRumbalski, dlaczego nie? Robi dokładnie to samo ... o ile wiem. Czy to tylko mniej Pythonic? Lub wolniej? – FakeRainBrigand

+0

Lambdas są * anonimowe * funkcje i doskonałe do tworzenia jednej wkładki. Tutaj przypisujesz nazwę lambda, co sugeruje, że byłoby lepiej jako zwykła funkcja. Ponadto, lambda zasłania twój traceback, gdy masz błąd. –

1

najłatwiej jest podzielić dane na dwie tablice char a następnie pętlę poprzez porównywanie liter i zwraca indeks gdy dwa znaki nie równa się nawzajem.

Ta metoda będzie działać poprawnie, o ile oba łańcuchy mają równą długość.

1

Sparuj łańcuchy znak po znaku i powtórz ten zbiór wraz z indeksem liczenia. Sprawdź, czy znaki w każdej parze różnią się; jeśli tak, wypisz indeks gdzie.

Korzystanie Pythonie funkcji wbudowanych można to zrobić porządnie w jednym wierszu:

>>> x = 'HELPMEPLZ' 
>>> y = 'HELPNEPLX' 
>>> {i for i, (left, right) in enumerate(zip(x,y)) if left != right} 
{8, 4} 
+0

Chociaż PO nie powiedział tak, byłbym skłonny założyć się, że rozwiązanie, które produkowało błędne wskaźniki w porządku rosnącym, byłoby lepsze. –

+0

@Linus: jeśli chcesz, zmień nawias '{}' na '[]'. To da ci zrozumienie listy zamiast ustawionego zrozumienia, więc zachowuje kolejność. – katrielalex

4
>>> from itertools import izip 
>>> s1 = 'HELPMEPLZ' 
>>> s2 = 'HELPNEPLX' 
>>> [i for i,(a1,a2) in enumerate(izip(s1,s2)) if a1!=a2] 
[4, 8] 
18

Spróbuj tego:

s1 = 'HELPMEPLZ' 
s2 = 'HELPNEPLX' 
[i for i in xrange(len(s1)) if s1[i] != s2[i]] 

on powróci:

> [4, 8] 

Powyższy rozwiązanie zwróci listę w z indeksami w porządku posortowanym, nie tworzy niepotrzebnych pośrednich struktur danych i będzie działać na Pythonie 2.3 - 2.7. Python 3.x zastępuje xrange dla range.

+0

'zip' to iterator w Pythonie 3. Nie jestem pewien, co masz na myśli przez komentarz w Pythonie 2.3. – katrielalex

+0

Oznacza to, że nie używa on funkcji specyficznych dla Pythona 3 - na przykład zakłada, że ​​zip jest iteratorem, lub że dostępne są ustawienia zrozumiałe. Moje rozwiązanie działa wydajnie nawet w starszych wersjach Pythona, o ile są dostępne wyliczenia list. –

+0

Ustawienia kompresji są w Pythonie 2.7. – katrielalex

9

Python naprawdę zawiera baterie. Wystarczy popatrzeć na difflib

>>> import difflib 
>>> a='HELPMEPLZ' 
>>> b='HELPNEPLX' 
>>> s = difflib.SequenceMatcher(None, a, b) 
>>> for block in s.get_matching_blocks(): 
...  print block 
Match(a=0, b=0, size=4) 
Match(a=5, b=5, size=3) 
Match(a=9, b=9, size=0) 

difflib jest bardzo silny, a niektóre badania dokumentacji jest bardzo zalecane.

Powiązane problemy