Sub-String-Extraktor mit bestimmten Schlüsselwörtern

Jan 07 2021

Herausforderung

Das Ziel dieser Herausforderung besteht darin, eine Funktion zu erstellen, die eine Eingabezeichenfolge, ein Startschlüsselwort und ein Endschlüsselwort verwendet. Das aus der Ausgabe extrahierte Ergebnis ist vom angegebenen Startschlüsselwort bis zum Endschlüsselwort (aber ausgeschlossen). Die Ausgabe-Unterzeichenfolge folgt den folgenden Regeln.

  • In allen Fällen sollten die führenden / nachfolgenden Leerzeichen in der Ausgabeunterzeichenfolge entfernt werden.

  • Wenn das angegebene Schlüsselwort start eine leere Zeichenfolge ist, bedeutet dies, dass sich der Anker am Anfang der Eingabezeichenfolge befindet. Andernfalls ist das erste Auftreten des angegebenen Startschlüsselworts ein Startanker. Wenn das angegebene Schlüsselwort start nicht vorkommt, ist die Ausgabe eine leere Zeichenfolge.

  • Wenn das angegebene Schlüsselwort end eine leere Zeichenfolge ist, bedeutet dies, dass sich der Anker am Ende der Eingabezeichenfolge befindet. Andernfalls ist das erste Auftreten des angegebenen Schlüsselworts end ein Endanker. Wenn das angegebene Schlüsselwort end nicht vorkommt, ist die Ausgabe eine leere Zeichenfolge.

  • Wenn die Position des Startankers nach der Position des Endankers liegt oder sich ein Teil des ersten Auftretens des angegebenen Startschlüsselworts und ein Teil des ersten Auftretens des angegebenen Endschlüsselworts überlappen, ist die Ausgabe eine leere Zeichenfolge.

Ähnlich, aber anders als beim Extrahieren einer Zeichenfolge aus einer bestimmten Zeichenfolge , bestehen die angegebenen Start- und Endanker aus mehreren Zeichen.

Hier ist eine ungolfed Referenzimplementierung in C #

private static string GetTargetString(string stringInput, string startKeywordInput, string endKeywordInput)
{
    int startIndex;
    if (String.IsNullOrEmpty(startKeywordInput))
    {
        startIndex = 0;
    }
    else 
    {
        if (stringInput.IndexOf(startKeywordInput) >= 0)
        {
            startIndex = stringInput.IndexOf(startKeywordInput) + startKeywordInput.Length;
        }
        else
        {
            return "";
        }
        
    }

    int endIndex;
    if (String.IsNullOrEmpty(endKeywordInput))
    {
        endIndex = stringInput.Length;
    }
    else
    {
        if (stringInput.IndexOf(endKeywordInput) > startIndex)
        {
            endIndex = stringInput.IndexOf(endKeywordInput);
        }
        else
        {
            return "";
        }
    }
    
    
    //    Check startIndex and endIndex
    if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex)
    {
        return "";
    }

    if (endIndex.Equals(0).Equals(true))
    {
        endIndex = stringInput.Length;
    }
    int TargetStringLength = endIndex - startIndex;
    return stringInput.Substring(startIndex, TargetStringLength).Trim();
}

Beispiel für Ein- und Ausgabe

Die Beispiel-Ein- und Ausgabe ist wie folgt aufgeführt.

Eingabezeichenfolge Schlüsselwort starten Schlüsselwort beenden Ausgabe
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ""(leerer String) ""(leerer String) "C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt."
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ""(leerer String) ".NETZ" "C # wurde um 2000 von Microsoft als Teil seiner"
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." "C #" ""(leerer String) "wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt"
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." "C #" ".NETZ" "wurde um 2000 von Microsoft im Rahmen seiner"
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ".NETZ" ""(leerer String) "Initiative"
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ""(leerer String) "C #" ""(leerer String)
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ".NETZ" "C #" ""(leerer String)
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." "ABC" "C #" ""(leerer String)
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." ".NETZ" "XYZ" ""(leerer String)
"C # wurde um 2000 von Microsoft im Rahmen seiner .NET-Initiative entwickelt." "ABC" "XYZ" ""(leerer String)

Regeln

Das ist Code-Golf . Die Antwort mit den wenigsten Bytes gewinnt.

Antworten

2 Adám Jan 07 2021 at 15:32

APL (Dyalog Extended) , 24 Byte ( SBCS )

Vollständiges Programm, das zur Eingabe eines Arrays von auffordert [EndKeyword,StartKeyword,InputString]. Erfordert eine 0-basierte Indizierung.

⌂deb⊃(⌽⊢↓⍨1⍳⍨⊣,⍷)/⌽¨@0⊢⎕

Probieren Sie es online aus!

 Eingabeaufforderung

 auf diesem…

⌽¨@0 Kehren Sie alle Elemente um, die bei Offset 0 auftreten

()/ Mit der folgenden stillschweigenden Funktion von rechts reduzieren:

 Geben Sie mit einer Booleschen Liste alle Stellen an, an denen das linke Argument im rechten Argument beginnt

⊣, Stellen Sie dem linken Argument das voran

1⍳⍨ Finden Sie den Versatz der ersten 1

⊢↓⍨ Löschen Sie so viele führende Elemente aus dem richtigen Argument

umkehren (beim nächsten Mal tun Sie dies ab dem Ende und danach die Reihenfolge zurücksetzen)

 offenbaren das Gehäuse, das durch die Reduktion von einem eindimensionalen Array zu einem 0-dimensionalen Array verursacht wird

⌂debd elete e nding (führende und nachfolgende ) b lanks

5 Arnauld Jan 07 2021 at 11:31

JavaScript (ES6),  80 bis  75 Byte

Dies enthält einige nicht druckbare Zeichen, die unten maskiert sind.

(s,a,b)=>s.replace(b||/$/,"").replace(a,"").match(/ *(.*?) *|$/)[1]||""

Probieren Sie es online aus!

Kommentiert

(s, a, b) =>          // s = input string, a = start keyword, b = end keyword
  s.replace(          // replace in s:
    b || /$/, // look for the end keyword, or the regex /$/ if it's empty
    "\3"              //   and replace it with ETX (end of text)
  )                   //
  .replace(           // replace in the resulting string:
    a,                //   look for the start keyword
    "\2"              //   and replace it with STX (start of text)
  )                   //
  .match(             // attempt to match:
    /\2 *(.*?) *\3|$/ // "\2" STX ) // " *" followed by optional whitespace // "(.*?)" followed by a non-greedy string (the payload) // " *" followed by optional whitespace // "\3" followed by ETX // "|$"    OR match an empty string to make sure that
                      //           match() doesn't return null
  [1] || ""           // return the payload string, or an empty string if undefined
3 Noodle9 Jan 08 2021 at 19:19

Python 3 , 86 77 75 Bytes

9 Bytes dank movatica gespart !!!
2 Bytes dank Ovs gespeichert !!!

lambda s,a,b:s[s.find(a):(b in s)*s.find(b)if b else None][len(a):].strip()

Probieren Sie es online aus!

1 tsh Jan 07 2021 at 13:12

JavaScript (Node.js) , 74 Byte

(s,a,b)=>s.substr(p=(s+a).indexOf(a)+a.length,b?s.indexOf(b)-p:1/0).trim()

Probieren Sie es online aus!

Recht einfach...

1 vrintle Jan 07 2021 at 11:57

Ruby , 66 Bytes

->w,s,e,r=Regexp{"#{w[/#{r.quote s}\K.+(?=#{r.quote e})/]}".strip}

Probieren Sie es online aus!

Eine andere Methode ohne die Verwendung von Regex,

Ruby , 72 Bytes

->w,s,e{"#{w[((w+s).index(s)+s.size rescue 0)...w.rindex(e)||0]}".strip}

Probieren Sie es online aus!

1 movatica Jan 08 2021 at 19:47

Python 3 , 100 85 Bytes

Die Regex-Version kann den Slicing-Algorithmus immer noch nicht übertreffen .

from re import*
r=escape
f=lambda s,b,e:(search(r(b)+'(.+)'+r(e),s)or'  ')[1].strip()

Probieren Sie es online aus!

1 Neil Jan 09 2021 at 19:04

Retina 0,8,2 , 60 Bytes

(.*)¶(.+)?¶.*?\1 *(.*?) *(?<!(?=\2).*)(?(2)\2.*|$)|(.|¶)+ $3

Probieren Sie es online aus! Nimmt die Eingabe als Start, Ende, Zeichenfolge in separaten Zeilen auf, aber die Verknüpfung dient zur Testsuite mit einem Header, der der Einfachheit halber aus einer durch Kommas getrennten Zeichenfolge, Ende und Start konvertiert wird. Erläuterung:

(.*)¶

Passen Sie das Schlüsselwort start an.

(.+)?¶

Entspricht optional einem nicht leeren End-Schlüsselwort.

.*?\1

Suchen Sie das Schlüsselwort start so früh wie möglich in der Zeichenfolge sowie optionale Leerzeichen.

 *(.*?) *

Passen Sie ein möglichst kurzes Ergebnis an (damit das Schlüsselwort end so früh wie möglich in der Zeichenfolge gefunden wird), aber schneiden Sie auch Leerzeichen um das Ergebnis herum ab.

(?<!(?=\2).*)

Stellen Sie sicher, dass das Schlüsselwort end zu diesem Zeitpunkt noch nicht übergeben wurde.

(?(2)\2.*|$)

Wenn das Schlüsselwort end leer war, stimmen Sie nur am Ende der Zeichenfolge überein, andernfalls stimmen Sie mit dem Schlüsselwort end und dem Rest der Zeichenfolge überein.

|(.|¶)+

Wenn es nicht möglich war, etwas abzugleichen, löschen Sie alles.

$3

Behalten Sie das gewünschte Ergebnis.

1 att Jan 07 2021 at 13:42

Wolfram Language (Mathematica) , 93 Bytes

sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&

Probieren Sie es online aus!

1 GalenIvanov Jan 07 2021 at 15:30

Rot , 90 Bytes

func[t s e][p:""if""<> s[append s" "]if e =""[e:[end]]parse t[thru s copy p to[opt" "e]]p]

Probieren Sie es online aus!

1 Davide Jan 10 2021 at 22:26

C (gcc) , 168 152 143 132 112 Bytes

Ein enormer -38 dank @ceilingcat

#define r strstr(c
*f(c,s,e)int*c,*s,*e;{return*e&&r,s)>r,e)|!r,s)|!r,e)||*e&&(*r,e)=0)?"":r,s)+strlen(s)+!!*s;}

Probieren Sie es online aus!

myjobistobehappy Jan 07 2021 at 13:05

JavaScript (ES6) 95 92 Bytes, kein Regex!

(i,s,e,t=i.indexOf(s),r=i.lastIndexOf(e))=>t!=-1&r!=-1?(i.substring(t+s.length,r)).trim():''

Wie man es versucht:

Öffnen Sie die JavaScript-Konsole Ihres Browsers und fügen Sie Folgendes ein.

((i,s,e,t=i.indexOf(s),r=i.lastIndexOf(e))=>t!=-1&r!=-1?(i.substring(t+s.length,r)).trim():'')('C# was developed around 2000 by Microsoft as part of its .NET initiative', 'C#', '.NET')
Neil Jan 09 2021 at 22:40

Holzkohle , 41 Bytes

≔⎇ζ…θ⌕θζθθ≔⎇η⪫Φ⪪θηκηθθ≔⌕AEθ›ι ¹ε¿ε✂θ⌊ε⊕⌈ε

Probieren Sie es online aus! Der Link führt zur ausführlichen Version des Codes. Achten Sie darauf, genügend Zeilenumbrüche in die Eingabe aufzunehmen, auch wenn eines der Schlüsselwörter leer ist. Erläuterung:

≔⎇ζ…θ⌕θζθθ

Wenn das Schlüsselwort end nicht leer ist, schneiden Sie die Zeichenfolge beim ersten Auftreten ab. (Glücklicherweise wird CycleChopdie Zeichenfolge abgeschnitten, um sie zu leeren, wenn ihre Eingabe negativ ist.)

≔⎇η⪫Φ⪪θηκηθθ

Wenn das Schlüsselwort start nicht leer ist, teilen Sie die Zeichenfolge auf das Schlüsselwort auf, verwerfen Sie das erste Element und verbinden Sie die Zeichenfolge erneut. Dies führt zu einer leeren Zeichenfolge, wenn das Schlüsselwort start nicht in der Zeichenfolge angezeigt wird.

≔⌕AEθ›ι ¹ε

Überprüfen Sie, ob die Zeichenfolge Leerzeichen enthält.

¿ε✂θ⌊ε⊕⌈ε

Wenn ja, drucken Sie vom ersten bis zum letzten Leerzeichen.

DominicvanEssen Jan 11 2021 at 06:31

R , 111 Bytes

function(s,a,b,c=?s,`?`=nchar,r=regexpr)trimws(substr(s,`if`((d=r(a,s,f=T))>0,d+?a,c),`if`(?b,r(b,s,f=T)-1,c)))

Probieren Sie es online aus!

Geradliniger Ansatz: Funde Worte begrenzt regexpr(mit dem Argumente fixed = True um sicherzustellen , dass die Textzeichenfolge nicht als Regex interpretiert), bekommen das substring zwischen ihnen, und dann trims das white sTempo von beiden Enden.

Da die Funktionen ncharund regexprjeweils zweimal verwendet werden, ist es kürzer, Aliase mit einem Zeichen zu definieren. Im Fall von ncharkönnen wir sogar den unären Operator ?als Alias neu definieren , sodass keine Klammern erforderlich sind. Leider ist dieser Trick hier nicht möglich, regexprda das zusätzliche Argument fixed = True eingegeben werden muss .

pinkfloydx33 Jan 24 2021 at 20:05

C # 114 Bytes

(i,s,e)=>{int p=(i+(s??="")).IndexOf(s)+s.Length,q=$"{e}"==""?i.Length:i.IndexOf(e);return p<q?i[p..q].Trim():"";}