Usuń duplikaty z ciągu

17

Zainspirowany tym skromnym pytaniem StackOverflow .

Pomysł jest prosty; biorąc pod uwagę Ciąg i tablicę Ciągów, usuń wszelkie wystąpienia słów w tablicy (ignorując wielkość liter) z wejściowego Ciągu innego niż pierwszy, a także wszelkie dodatkowe białe znaki, które może zostawić. Słowa muszą pasować do całych słów w ciągu wejściowym, a nie do części słów.

na przykład "A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", ["cat", "mat"] powinien generować"A cat called matt sat on a mat and wore a hat A called matt sat on a and wore a hat"

Wejście

  • Dane wejściowe można traktować jako ciąg znaków oraz tablicę ciągów lub tablicę ciągów, w których ciąg wejściowy jest pierwszym elementem. Parametry te mogą być w dowolnej kolejności.
  • Ciąg wejściowy nie może być traktowany jako lista ciągów rozdzielanych spacjami.
  • Łańcuch wejściowy nie będzie zawierał spacji wiodących, końcowych ani kolejnych.
  • Wszystkie dane wejściowe będą zawierać tylko znaki [A-Za-z0-9], z wyjątkiem ciągu wejściowego również ze spacjami.
  • Tablica wejściowa może być pusta lub zawierać słowa spoza wejściowego ciągu znaków.

Wynik

  • Dane wyjściowe mogą być albo wartością zwracaną z funkcji, albo drukowane do STDOUT
  • Dane wyjściowe muszą być w tym samym przypadku, co oryginalny ciąg

Przypadki testowe

the blue frog lived in a blue house, [blue] -> the blue frog lived in a house
he liked to read but was filled with dread wherever he would tread while he read, [read] -> he liked to read but was filled with dread wherever he would tread while he
this sentence has no matches, [ten, cheese] -> this sentence has no matches
this one will also stay intact, [] -> this one will also stay intact
All the faith he had had had had no effect on the outcome of his life, [had] -> All the faith he had no effect on the outcome of his life
5 times 5 is 25, [5, 6] -> 5 times is 25
Case for different case, [case] -> Case for different
the letters in the array are in a different case, [In] -> the letters in the array are a different case
This is a test Will this be correct Both will be removed, [this,will] -> This is a test Will be correct Both be removed

Ponieważ jest to kod golfowy, wygrywa najmniejsza liczba bajtów!

Luke Stevens
źródło

Odpowiedzi:

9

R , 84 bajtów

function(s,w,S=el(strsplit(s," ")),t=tolower)cat(S[!duplicated(x<-t(S))|!x%in%t(w)])

Wypróbuj online!

Mniej niż 100 bajtów na wyzwaniu, które nie jest również ?

Wyjaśnienie:

Po rozbiciu ciągu na słowa musimy wykluczyć te, które są

  1. duplikaty i
  2. w w

lub alternatywnie, obracając to na głowie, trzymając te, które są

  1. pierwsze wystąpienie słowa OR
  2. nie w w.

duplicatedstarannie zwraca logiczne wskaźniki dla tych, które nie są pierwszym wystąpieniem, więc !duplicated()zwraca indeks dla tych, które są pierwsze, i x%in%wzwraca logiczne wskaźniki dla xtych, które są w w. Schludny.

Giuseppe
źródło
6

Java 8, 117 110 bajtów

a->s->{for(String x:a)for(x="(?i)(.*"+x+".* )"+x+"( |$)(.*)";s.matches(x);s=s.replaceAll(x,"$1$3"));return s;}

Wyjaśnienie:

Wypróbuj online.

a->s->{                // Method with String-array and String parameters and String return
  for(String x:a)      //  Loop over the input-array
    for(x="(?i)(.*"+x+".* )"+x+"( |$)(.*)";
                       //   Regex to match
        s.matches(x);  //   Inner loop as long as the input matches this regex
      s=s.replaceAll(x,"$1$3")); 
                       //    Replace the regex-match with the 1st and 3rd capture groups
  return s;}           //  Return the modified input-String

Dodatkowe wyjaśnienie wyrażenia regularnego:

(?i)(.*"+x+".* )"+x+"( |$)(.*)   // Main regex to match:
(?i)                             //  Enable case insensitivity
    (                            //  Open capture group 1
     .*                          //   Zero or more characters
       "+x+"                     //   The input-String
            .*                   //   Zero or more characters, followed by a space
               )                 //  End of capture group 1
                "+x+"            //  The input-String again
                     (           //  Open capture group 2
                       |$        //   Either a space or the end of the String
                         )       //  End of capture group 2
                          (      //  Open capture group 3
                           .*    //   Zero or more characters
                             )   //  End of capture group 3

$1$3                             // Replace the entire match with:
$1                               //  The match of capture group 1
  $3                             //  concatted with the match of capture group 3
Kevin Cruijssen
źródło
4

MATL , 19 18 bajtów

"Ybtk@kmFyfX<(~)Zc

Dane wejściowe to: tablica komórek zawierająca ciągi, a następnie ciąg.

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Jak to działa

"        % Take 1st input (implicit): cell array of strings. For each
  Yb     %   Take 2nd input (implicit) in the first iteration: string; or
         %   use the string from previous iteration. Split on spaces. Gives
         %   a cell array of strings
  tk     %   Duplicate. Make lowercase
  @k     %   Push current string from the array taken as 1st input. Make
         %   lowercase
  m      %   Membership: gives true-false array containing true for strings
         %   in the first input argument that equal the string in the second
         %   input argument
  F      %   Push false
  y      %   Duplicate from below: pushes the true-false array again
  f      %   Find: integer indices of true entries (may be empty)
  X<     %   Minimum (may be empty)
  (      %   Assignment indexing: write false in the true-false array at that
         %   position. So this replaces the first true (if any) by false
  ~      %   Logical negate: false becomes true, true becomes false
  )      %   Reference indexing: in the array of (sub)strings that was
         %   obtained from the second input, keep only those indicated by the
         %   (negated) true-false array
  Zc     %   Join strings in the resulting array, with a space between them
         % End (implicit). Display (implicit)
Luis Mendo
źródło
3

Perl 5 , 49 bajtów

@B=<>;$_=join$",grep!(/^$_$/xi~~@B&&$v{+lc}++),@F

Wypróbuj online!

Zaoszczędź 9 (!!) bajtów dzięki @TonHospel !

Dom Hastings
źródło
1
To wydaje się nie działać dla This is a test Will this be correct Both will be removed+ this will. Drugie dwa słowa zostały poprawnie usunięte, ale z jakiegoś powodu również usunęły bepo drugim will.
Kevin Cruijssen
1
@KevinCruijssen Hmmm, rozumiem, dlaczego tak się dzieje. Spróbuję jutro odpowiednio przyjrzeć się lunchowi, ale na razie naprawiłem to za cenę +4. Dzięki, że dałeś mi znać!
Dom Hastings,
Za 49:@B=<>;$_=join$",grep!(/^$_$/xi~~@B&&$v{+lc}++),@F
Ton Hospel
@TonHospel Ahh, spędziłem trochę czasu próbując lczostać wezwanym bez parens. Niesamowite! A użycie wyrażenia regularnego względem tablicy jest znacznie lepsze, dziękuję! Z trudem pamiętam wszystkie twoje wskazówki!
Dom Hastings
2

Pyth, 27 bajtów

jdeMf!}r0eT@mr0dQmr0dPT._cz

Wypróbuj online

Wyjaśnienie

jdeMf!}r0eT@mr0dQmr0dPT._cz
                          z  Take the string input.
                       ._c   Get all the prefixes...
    f    eT@                 ... which end with something...
     !}         Q    PT      ... which is not in the input and the prefix...
       r0   mr0d mr0d        ... case insensitive.
jdeM                         Join the ends of each valid prefix.

Jestem pewien, że 10 bajtów dla sprawdzania bez rozróżniania wielkości liter można zmniejszyć, ale nie wiem, jak to zrobić.


źródło
2

Stax , 21 bajtów CP437

åìøΓ²¬$M¥øHΘQä~╥ôtΔ♫╟

25 bajtów po rozpakowaniu,

vjcm[]Ii<;e{vm_]IU>*Ciyj@

Wynikiem jest tablica. Wygodnym wyjściem dla Stax jest jeden element na linię.

Uruchom i debuguj online!

Wyjaśnienie

vj                           Convert 1st input to lowercase and split at spaces,
  c                          Duplicate at the main stack
   m                         Map array with the rest of the program 
                                 Implicitly output
    []I                      Get the first index of the current array element in the array
       i<                    Test 1: The first index is smaller than the iteration index
                                 i.e. not the first appearance
         ;                   2nd input
          {vm                Lowercase all elements
             _]I             Index of the current element in the 2nd input (-1 if not found)
                U>           Test 2: The index is non-negative
                                 i.e. current element is a member of the 2nd input
                  *C         If test 1 and test 2, drop the current element
                                 and go on mapping the next
                    iyj@     Fetch the corresponding element in the original input and return it as the mapped result
                                 This preserves the original case
Weijun Zhou
źródło
2

Perl 6 , 49 bajtów

->$_,+w{~.words.grep:{.lcw».lc||!(%){.lc}++}}

Sprawdź to

Rozszerzony:

->              # pointy block lambda
  $_,           # first param 「$_」 (string)
  +w            # slurpy second param 「w」 (words)
{

  ~             # stringify the following (joins with spaces)

  .words        # split into words (implicit method call on 「$_」)

  .grep:        # take only the words we want

   {
     .lc        # lowercase the word being tested
               # is it not an element of
     w».lc      # the list of words, lowercased

     ||         # if it was one of the words we need to do a secondary check

     !          # Boolean invert the following
                # (returns true the first time the word was found)

     (
       %        # anonymous state Hash variable
     ){ .lc }++ # look up with the lowercase of the current word, and increment
   }
}
Brad Gilbert b2gills
źródło
2

Perl 5 , 50 48 bajtów

Obejmuje +1dla-p

Podaj ciąg docelowy, po którym następuje każde słowo filtru, w osobnych wierszach STDIN:

perl -pe '$"="|";s%\b(@{[<>]})\s%$&x!$v{lc$1}++%iegx;chop';echo
This is a test Will this be correct Both will be removed
this
will
^D
^D

Jest chopto potrzebne tylko do poprawienia spacji końcowej w przypadku usunięcia ostatniego słowa

Tylko kod:

$"="|";s%\b(@{[<>]})\s%$&x!$v{lc$1}++%iegx;chop

Wypróbuj online!

Ton Hospel
źródło
1

JavaScript (ES6), 98 bajtów

s=>a=>s.split` `.filter(q=x=>(q[x=x.toLowerCase()]=eval(`/\\b${x}\\b/i`).test(a)<<q[x])<2).join` `
ETHprodukcje
źródło
1

K4 , 41 bajtów

Rozwiązanie:

{" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}

Przykłady:

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat";("cat";"mat")]
"A cat called matt sat on a mat and wore a hat A called matt sat on a and wore a hat"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["Case for different case";enlist "case"]
"Case for different"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["the letters in the array are in a different case";enlist "In"]
"the letters in the array are a different case"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["5 times 5 is 25";(1#"5";1#"6")]
"5 times is 25"

Wyjaśnienie:

Podziel na białe znaki, małe litery na obu wejściach, wyszukaj dopasowania, usuń wszystkie wystąpienia oprócz pierwszego, ponownie połącz ciąg znaków.

{" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x} / the solution
{                                       } / lambda with implicit x & y args
                                  " "\:x  / split (\:) on whitespace " "
                                x:        / save result as x
                               _          / lowercase x
                          ~/:\:           / match (~) each right (/:), each left (\:)
                      (_y)                / lowercase y
                   &:'                    / where (&:) each ('), ie indices of matches
                1_'                       / drop first of each result
              ,/                          / flatten
            y:                            / save result as y
         y@>                              / descending indices (>) apply (@) to y
      x_/                                 / drop (_) from x
 " "/:                                    / join (/:) on whitespace " "
streetster
źródło
1

JavaScript (Node.js) , 75 bajtów

f=(s,a)=>a.map(x=>s=s.replace(eval(`/\\b${x}\\b */ig`),s=>i++?"":s,i=0))&&s

Wypróbuj online!

DanielIndie
źródło
1
Ponieważ nie jest to funkcja rekurencyjna, nie musisz uwzględniać f=w swojej liczbie bajtów. Można również zapisać bajt przez currying parametry, zastępując (s,a)=>przy s=>a=>czym wywołanie funkcji z f(s)(a).
Kudłaty
@ Shaggy tak, ale naprawdę mam na myśli grę w golfa w definicji tej funkcji, ponieważ głównym celem jest gra w ciało. ale dzięki, to dobra wskazówka :)
DanielIndie
1

JavaScript ES6, 78 bajtów

f=(s,a,t={})=>s.split` `.filter(w=>a.find(e=>w==e)?(t[w]?0:t[w]=1):1).join` `

Jak to działa:

f=(s,a,t={})=> // Function declaration; t is an empty object by default
s.split` ` // Split the string into an array of words
.filter(w=> // Declare a function that, if it returns false, will delete the word
  a.find(e=>w==e) // Returns undeclared (false) if the word isn't in the list
  ?(t[w]?0 // If it is in the list and t[w] exists, return 0 (false)
    :t[w]=1) // Else make t[w] exist and return 1 (true)
  :1) // If the word isn't in the array, return true (keep the word for sure)
.join` ` // Rejoin the string
Ian
źródło
2
Witamy w PPCG! Ponieważ nie używasz nazwy funkcji fdo wywołania rekurencyjnego, funkcja nienazwana również byłaby poprawnym przesłaniem, więc możesz zapisać dwa bajty, upuszczając f=.
Martin Ender
Witamy w PPCG! Niestety nie udaje się to w przypadku różnych przypadków.
Kudłaty
Gdyby tak nie było, można by sprowadzić to do 67 bajtów
Kudłaty
@MartinEnder Dzięki za wskazówkę!
Ian
@Shaggy używanie tablicy wejściowej jako obiektu to ciekawy pomysł, o którym nawet nie myślałem. Spróbuję naprawić problem ze sprawą.
Ian
0

PowerShell v3 lub nowszy, 104 bajty

Param($s,$w)$w|?{$_-and$s-match($r="\b$_(?: |$)")}|%{$h,$t=$s-split$r;$s="$h$($Matches.0)$(-join$t)"};$s

Kosztem jednego bajtu można go uruchomić w PS 2.0, zastępując $Matches.0go $Matches[0].

Długa wersja:

Param($s, $w)
$w | Where-Object {$_ -and $s -match ($r = "\b$_(?: |$)")} |    # Process each word in the word list, but only if it matches the RegEx (which will be saved in $r).
    ForEach-Object {                                            # \b - word boundary, followed by the word $_, and either a space or the end of the string ($)
        $h, $t = $s -split $r                                   # Split the string on all occurrences of the word; the first substring will end up in $h(ead), the rest in $t(ail) (might be an array)
        $s = "$h$($Matches.0)$(-join $t)"                       # Create a string from the head, the first match (can't use the word, because of the case), and the joined tail array
    }
$s                                                              # Return the result

Zastosowanie
Zapisz jako Whokolwiek.ps1 i wywołaj z ciągiem znaków i słowami jako argumentami. Jeśli trzeba przekazać więcej niż jedno słowo, należy je zawinąć w @ ():

.\Whatever.ps1 -s "A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat" -w @("cat", "mat")

Alternatywnie bez pliku (można wkleić bezpośrednio do konsoli PS):
Zapisz skrypt jako ScriptBlock (wewnątrz nawiasów klamrowych) w zmiennej, a następnie wywołaj jego metodę Invoke () lub użyj go z Invoke-Command:

$f={Param($s,$w)$w|?{$_-and$s-match($r="\b$_(?: |$)")}|%{$h,$t=$s-split$r;$s="$h$($Matches.0)$(-join$t)"};$s}
$f.Invoke("A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", @("cat", "mat"))
Invoke-Command -ScriptBlock $f -ArgumentList "A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", @("cat", "mat")
użytkownik314159
źródło
0

JavaScript, 150 bajtów

s=(x, y)=>{let z=new Array(y.length).fill(0);let w=[];for(f of x)(y.includes(f))?(!z[y.indexOf(f)])&&(z[y.indexOf(f)]=1,w.push(f)):w.push(f);return w}
bramkarz
źródło
Oprócz problemów z golfem (spójrz na inne rozwiązania JS, aby uzyskać tam kilka wskazówek), bierze to pierwsze wejście jako tablicę słów i wyświetla tablicę słów, która nie jest dozwolona w specyfikacji wyzwania. Nie powiedzie się również, gdy w grę wchodzą różne sprawy.
Kudłaty
@Shaggy „Wyjście może być wartością zwracaną z funkcji” Wygląda na to, że zwraca wartość z funkcji?
aimorris
0

Czysty , 153 142 138 134 bajtów

import StdEnv,StdLib,Text
@ =toUpperCase
$s w#s=split" "s
=join" "[u\\u<-s&j<-[0..]|and[i<>j\\e<-w,i<-drop 1(elemIndices(@e)(map@s))]]

Wypróbuj online!

Definiuje funkcję $ :: String [String] -> String, praktycznie dosłownie robiąc to, co opisuje wyzwanie. Znajduje i usuwa każde wystąpienie po pierwszym, dla każdego słowa docelowego.

Obrzydliwe
źródło
0

Siatkówka, 46 37 bajtów

+i`(^|,)((.+),.*\3.* )\3( |$)
$2
.*,

-14 bajtów dzięki @Neil i +5 bajtów za naprawę błędu.

Dane wejściowe w formacie word1,word2,word3,sentence, ponieważ nie jestem pewien, jak wprowadzić dane wieloliniowe (gdzie dane wejściowe są używane inaczej).

Wyjaśnienie:

Wypróbuj online.

+i`(^|,)((.+),.*\3.* )\3( |$)   Main regex to match:
+i`                              Enable case insensitivity
   (^|,)                          Either the start of the string, or a comma
        (                         Open capture group 2
         (                         Open capture group 3
          .+                        1 or more characters
            )                      Close capture group 3
             ,                     A comma
              .*                   0 or more characters
                \3                 The match of capture group 3
                  .*               0 or more characters, followed by a space
                     )            Close capture group 2
                      \3          The match of capture group 2 again
                        ( |$)     Followed by either a space, or it's the end of the string
$2                              And replace everything with:
                                 The match of capture group 2

.*,                             Then get everything before the last comma (the list)
                                 and remove it (including the comma itself)
Kevin Cruijssen
źródło
1
Jak napisano, możesz uprościć pierwszą linię do +i`((.+),.*\2.* )\2( |$)drugiej, $1ale zauważam, że twój kod i often,he intended to keep ten geesetak nie działa .
Neil
@Neil Dzięki za golfa -14 i naprawiłem błąd z +1.
Kevin Cruijssen
... poza tym, że teraz nie udaje się to w jednym z oryginalnych przypadków testowych ...
Neil
@Neil Ah oops .. Naprawiono ponownie dla +4 bajtów.
Kevin Cruijssen
Cóż, dobrą wiadomością jest to, że myślę, że możesz użyć \bzamiast (^|,), ale złą wiadomością jest, że myślę, że potrzebujesz \b\3\b(chociaż nie opracowałem jeszcze odpowiedniego przypadku testowego).
Neil
0

Czerwony , 98 bajtów

func[s w][foreach v w[parse s[thru[any" "v ahead" "]any[to remove[" "v ahead[" "| end]]| skip]]]s]

Wypróbuj online!

f: func [s w][ 
    foreach v w [                   ; for each string in the array
        parse s [                   ; parse the input string as follows:
            thru [                  ; keep everything thru: 
                any " "             ; 0 or more spaces followed by
                v                   ; the current string from the array followed by
                ahead " "           ; look ahead for a space
            ]
            any [ to remove [       ; 0 or more: keep to here; then remove: 
                " "                 ; a space followed by 
                v                   ; the current string from the array
                ahead [" " | end]]  ; look ahead for a space or the end of the string
            | skip                  ; or advance the input by one 
            ]
        ]
    ]
    s                               ; return the processed string 
]
Galen Iwanow
źródło
0

Łuska , 13 bajtów

wüöVËm_Ṗ3+⁰ew

Bierze listę ciągów i pojedynczy ciąg jako argumenty, w tej kolejności. Zakłada, że ​​lista nie zawiera duplikatów. Wypróbuj online!

Wyjaśnienie

wüöVËm_Ṗ3+⁰ew  Inputs: list of strings L (explicit, accessed with ⁰), string S (implicit).
               For example, L = ["CASE","for"], s = "Case for a different case".
            w  Split S on spaces: ["Case","for","a","different","case"]
 ü             Remove duplicates wrt an equality predicate.
               This means that a function is called on each pair of strings,
               and if it returns a truthy value, the second one is removed.
  öVËm_Ṗ3+⁰e    The predicate. Arguments are two strings, say A = "Case", B = "case".
           e    Put A and B into a list: ["Case","case"]
         +⁰     Concatenate with L: ["CASE","for","Case","case"]
       Ṗ3       All 3-element subsets: [["CASE","for","Case"],["CASE","for","case"],
                                        ["CASE","Case","case"],["for","Case","case"]]
  öV            Does any of them satisfy this:
    Ë            All strings are equal
     m_          after converting each character to lowercase.
                In this case, ["CASE","Case","case"] satisfies the condition.
               Result: ["Case","for","a","different"]
w              Join with spaces, print implicitly.
Zgarb
źródło
0

Min. 125 bajtów

=a () =b a 1 get =c a 0 get " " split
(:d (b d in?) ((c d in?) (d b append #b) unless) (d b append #b) if) foreach
b " " join

Dane wejściowe są quotna stosie z ciągiem wejściowym jako pierwszym elementem, a quotzduplikowanymi łańcuchami jako drugim elementem, tj

("this sentence has no matches" ("ten" "cheese"))
Panda0nEarth
źródło
0

Python 3 , 168 bajtów

def f(s,W):
 s=s.split(" ");c={w:0for w in W}
 for w in W: 
  for i,v in enumerate(s):
   if v.lower()==w.lower():
    c[w]+=1
    if c[w]>1:s.pop(i)
 return" ".join(s)

Wypróbuj online!

Trelzevir
źródło
0

AWK , 120 bajtów

NR%2{for(;r++<NF;)R[tolower($r)]=1}NR%2==0{for(;i++<NF;$i=$(i+s))while(R[x=tolower($(i+s))])U[x]++?++s:i++;NF-=s}NR%2==0

Wypróbuj online!

Część „usuń białe znaki” sprawiła, że ​​było to nieco trudniejsze, niż początkowo myślałem. Ustawienie pola na ""usuwa pole, ale pozostawia dodatkowy separator.

Łącze TIO ma 28 dodatkowych bajtów, aby umożliwić wiele wpisów.

Dane wejściowe podawane są w 2 liniach. Pierwszy wiersz to lista słów, a drugi to „zdanie”. Zauważ, że „słowo” i „słowo” nie są uważane za identyczne z dołączoną interpunkcją. Posiadanie wymagań interpunkcyjnych sprawiłoby, że byłby to jeszcze bardziej zabawny problem.

Robert Benson
źródło
0

Rubinowy , 63 61 60 59 bajtów

->s,w{w.any?{|i|s.sub! /\b(#{i}\b.*) #{i}\b/i,'\1'}?redo:s}

Wypróbuj online!

Krótsza wersja, która rozróżnia wielkość liter i zawiesza ~ co 10 15 razy z powodu losowości (37 bajtów)

->s,w{s.uniq{|i|w.member?(i)?i:rand}}
Asone Tuhid
źródło
0

Python 2 , 140 bajtów

from re import*
p='\s?%s'
S,A=input()
for a in A:S=sub(p%a,lambda s:s.end()==search(p%a,S,flags=I).end()and s.group()or'',S,flags=I)
print S

Wypróbuj online!

Wyjaśnienie:

re.sub(..)może przyjąć jako argument funkcję zamiast ciągu zastępującego. Mamy więc trochę fantazyjnej lambdy. Wywoływana jest funkcja dla każdego wystąpienia wzorca i do tej funkcji przekazywany jest jeden obiekt - matchobject. Ten obiekt zawiera informacje o założonym wystąpieniu. Interesuje mnie indeks tego wystąpienia, który można odzyskać przez start()lub end()funkcję. Późniejszy jest krótszy, więc jest używany.

Aby wykluczyć zamianę pierwszego wystąpienia słowa, użyłem innej funkcji wyszukiwania wyrażenia regularnego, aby uzyskać dokładnie pierwszą, a następnie porównać indeksy, używając tego samego end()

Flaga re.Ito krótka wersjare.IGNORECASES

Dead Possum
źródło