Szukam regex
wzoru, który będzie pasował do trzeciego, czwartego, ... wystąpienia każdej postaci. Spójrz na wyjaśnienia poniżej:
Na przykład mam następujący ciąg:
111aabbccxccybbzaa1
Chcę zastąpić wszystkie zduplikowane znaki po drugim wystąpieniu. Dane wyjściowe będą:
11-aabbccx--y--z---
Niektóre wzorce wyrażeń regularnych, które próbowałem do tej pory:
Korzystając z następującego wyrażenia regularnego, mogę znaleźć ostatnie wystąpienie każdej postaci: (.)(?=.*\1)
Lub korzystając z tego mogę zrobić to dla kolejnych duplikatów, ale nie dla żadnych duplikatów: ([a-zA-Z1-9])\1{2,}
(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)
wyrażeniem regularnym. Demo .(.)(?<=(.*\1){3})
?(.)(?<=(?:.*\1){3})
również wykona zadanie, ale nie są one dobre, ponieważ nadmierne cofanie może powodować problemy z dłuższymi ciągami. Wolę napisać metodę niebędącą wyrażeniem regularnym, aby rozwiązać problem.(.)(?<=(?:.*\1){3})
25ms,(.)(?<=(?:\1.*?){2}\1)
3ms. Możesz po prostu sprawdzić się. Twój wydaje się być najmniej wydajnym wzorcem i najtrudniej go odczytać.Odpowiedzi:
Rozwiązanie typu non-regex R. Podzielony ciąg. Zamień elementy tego wektora o rowid> = 3 * na
'-'
. Wklej to z powrotem razem.*
rowid(x)
jest wektorem liczb całkowitych, w którym każdy element reprezentuje liczbęx
zrealizowanych wartości z odpowiedniego elementu . Więc jeśli ostatni elementx
jest1
, i to po raz czwarty1
wystąpił wx
, ostatni elementrowid(x)
jest4
.źródło
Możesz to łatwo zrobić bez wyrażenia regularnego:
Zobacz używany kod tutaj
Wynik:
Jak to działa:
for u in set(s)
pobiera listę unikalnych znaków w ciągu:{'c','a','b','y','1','z','x'}
for i in ...
pętle nad indeksami, które zbieramy w 3.[i for i in range(len(s)) if s[i]==u][2:]
zapętla każdy znak w ciągu i sprawdza, czy pasujeu
(od kroku 1.), a następnie przecina tablicę od drugiego elementu do końca (upuszczając dwa pierwsze elementy, jeśli istnieją)s[:i]+'-'+s[i+1:]
- połączyć podłańcuch do indeksu,-
a następnie podłańcuch po indeksie, skutecznie pomijając oryginalny znak.źródło
Opcja z
gsubfn
dane
źródło
Brak wyrażenia regularnego Python w jednym wierszu:
Wylicza to przez ciąg, licząc wystąpienia bieżącego znaku za nim i umieszczając znak tylko, jeśli jest jednym z pierwszych 2, w przeciwnym razie myślnik.
źródło
Kolejny sposób na zrobienie tego
pandas
.Wyjście :
źródło
Podziękowania dla Wiktora Stribiżew , Stefana Pochmanna i bobble bubble . W celu uzupełnienia zamieszczam możliwe
regex
rozwiązania omówione w komentarzach;Jest to możliwe tylko w przypadku wyrażenia regularnego obsługującego wygląd nieskończonej szerokości. Za pomocą modułu regex Python PyPi możemy wykonać następujące czynności:
Snippet .
źródło