Extracteur de sous-chaînes avec des mots clés spécifiques

Jan 07 2021

Défi

Le but de ce défi est de créer une fonction qui prend une chaîne d'entrée, un mot-clé de début et un mot-clé de fin. Le résultat extrait de la sortie est du (mais exclu) du mot clé de début donné au mot clé de fin (mais exclu). La sous-chaîne de sortie suit les règles ci-dessous.

  • Dans tous les cas, les espaces de début / de fin dans la sous-chaîne de sortie doivent être supprimés.

  • Si le mot-clé de début donné est une chaîne vide, cela signifie que l'ancre est au début de la chaîne d'entrée. Sinon, la première occurrence du mot-clé de début donné est une ancre de départ. S'il n'y a aucune occurrence du mot-clé de début donné, la sortie est une chaîne vide.

  • Si le mot-clé end donné est une chaîne vide, cela signifie que l'ancre est à la fin de la chaîne d'entrée. Sinon, la première occurrence du mot-clé end donné est une ancre de fin. S'il n'y a aucune occurrence du mot-clé end donné, la sortie est une chaîne vide.

  • Si l'emplacement de l'ancre de début est après l'emplacement de l'ancre de fin, ou si une partie de la première occurrence du mot-clé de début donné et une partie de la première occurrence du mot-clé de fin donné se chevauchent, la sortie est une chaîne vide.

Similaire mais différent de Extraire une chaîne d'une chaîne donnée , les ancres de début et de fin données sont des caractères multiples.

Voici une implémentation de référence non golfée en 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();
}

Exemple d'entrée et de sortie

L'exemple d'entrée et de sortie est répertorié ci-dessous.

Chaîne d'entrée Mot-clé de démarrage Mot-clé de fin Production
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ""(chaîne vide) ""(chaîne vide) "C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET"
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ""(chaîne vide) ".NET" "C # a été développé vers 2000 par Microsoft dans le cadre de son"
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" "C #" ""(chaîne vide) "a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET"
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" "C #" ".NET" "a été développé vers 2000 par Microsoft dans le cadre de son"
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ".NET" ""(chaîne vide) "initiative"
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ""(chaîne vide) "C #" ""(chaîne vide)
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ".NET" "C #" ""(chaîne vide)
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" "ABC" "C #" ""(chaîne vide)
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" ".NET" "XYZ" ""(chaîne vide)
"C # a été développé vers 2000 par Microsoft dans le cadre de son initiative .NET" "ABC" "XYZ" ""(chaîne vide)

Règles

C'est du code-golf . La réponse avec le moins d'octets l'emporte.

Réponses

2 Adám Jan 07 2021 at 15:32

APL (Dyalog Extended) , 24 octets ( SBCS )

Programme complet qui demande un tableau de [EndKeyword,StartKeyword,InputString]. Nécessite une indexation basée sur 0.

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

Essayez-le en ligne!

 demande de saisie

 sur ça…

⌽¨@0 inverser tous les éléments qui se produisent à l'offset 0

()/ Réduire à partir de la droite en utilisant la fonction tacite suivante:

 indiquer avec une liste booléenne tous les endroits où l'argument de gauche commence dans l'argument de droite

⊣, ajouter l'argument de gauche à cela

1⍳⍨ trouver le décalage du premier 1

⊢↓⍨ supprimer autant d'éléments principaux du bon argument

inverser (la prochaine fois, faites-le à partir de la fin, puis inversez l'ordre)

 divulguer l'enceinte provoquée par la réduction d'un tableau à une dimension à un tableau à 0 dimension

⌂debd elete e Nding (avant et arrière) b Lanks

5 Arnauld Jan 07 2021 at 11:31

JavaScript (ES6),  80  75 octets

Cela contient des caractères non imprimables qui sont échappés ci-dessous.

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

Essayez-le en ligne!

Commenté

(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 octets

Sauvegardé 9 octets grâce à movatica !!!
Sauvegardé 2 octets grâce à ovs !!!

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

Essayez-le en ligne!

1 tsh Jan 07 2021 at 13:12

JavaScript (Node.js) , 74 octets

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

Essayez-le en ligne!

Assez simple...

1 vrintle Jan 07 2021 at 11:57

Rubis , 66 octets

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

Essayez-le en ligne!

Une autre méthode sans l'utilisation de regex,

Rubis , 72 octets

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

Essayez-le en ligne!

1 movatica Jan 08 2021 at 19:47

Python 3 , 100 85 octets

La version Regex, ne peut toujours pas battre l' algorithme de découpage .

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

Essayez-le en ligne!

1 Neil Jan 09 2021 at 19:04

Retina 0.8.2 , 60 octets

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

Essayez-le en ligne! Prend l'entrée comme début, fin, chaîne sur des lignes séparées, mais le lien est vers la suite de tests avec un en-tête qui convertit à partir de la chaîne séparée par des virgules, fin, début pour plus de commodité. Explication:

(.*)¶

Faites correspondre le mot-clé de début.

(.+)?¶

Faire correspondre éventuellement un mot-clé de fin non vide.

.*?\1

Recherchez le mot-clé de début le plus tôt possible dans la chaîne, plus les espaces facultatifs.

 *(.*?) *

Faites correspondre un résultat aussi court que possible (afin que le mot-clé end soit trouvé le plus tôt possible dans la chaîne), mais supprimez également les espaces autour de celui-ci.

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

Assurez-vous que le mot-clé de fin n'a pas déjà été transmis à ce stade.

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

Si le mot-clé de fin était vide, ne correspond qu'à la fin de la chaîne, sinon correspond au mot-clé de fin et au reste de la chaîne.

|(.|¶)+

S'il n'est pas possible de faire correspondre quoi que ce soit, supprimez tout.

$3

Conservez le résultat souhaité.

1 att Jan 07 2021 at 13:42

Wolfram Language (Mathematica) , 93 octets

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

Essayez-le en ligne!

1 GalenIvanov Jan 07 2021 at 15:30

Rouge , 90 octets

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

Essayez-le en ligne!

1 Davide Jan 10 2021 at 22:26

C (gcc) , 168 152 143 132 112 octets

Un énorme -38 grâce à @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;}

Essayez-le en ligne!

myjobistobehappy Jan 07 2021 at 13:05

JavaScript (ES6) 95 92 octets, pas de regex!

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

Comment l'essayer:

Ouvrez la console JavaScript de votre navigateur et collez ce qui suit.

((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

Charbon , 41 octets

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

Essayez-le en ligne! Le lien est vers la version verbeuse du code. Veillez à inclure suffisamment de nouvelles lignes dans l'entrée même si l'un des mots-clés est vide. Explication:

≔⎇ζ…θ⌕θζθθ

Si le mot-clé end n'est pas vide, tronquez la chaîne à sa première apparition. (Heureusement, CycleChoptronque la chaîne pour qu'elle soit vide si son entrée est négative.)

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

Si le mot-clé de début n'est pas vide, divisez la chaîne sur le mot-clé, supprimez le premier élément et rejoignez la chaîne. Il en résulte une chaîne vide si le mot-clé de début n'apparaît pas dans la chaîne.

≔⌕AEθ›ι ¹ε

Vérifiez si la chaîne ne contient pas d'espaces.

¿ε✂θ⌊ε⊕⌈ε

Si tel est le cas, imprimez du premier au dernier non-espace.

DominicvanEssen Jan 11 2021 at 06:31

R , 111 octets

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)))

Essayez-le en ligne!

Approche simple: trouvailles limitant l' utilisation des mots regexpr(avec l' argument fMMOBILISATIONS = True pour faire en sorte que la chaîne de texte ne soit pas interprété comme une expression régulière), obtient le crée substrentre elles, puis trims le wHite srythme des deux extrémités.

Puisque les fonctions ncharet regexprsont chacune utilisées deux fois, il est plus court de définir des alias à un seul caractère. Dans le cas de nchar, nous pouvons même redéfinir l'opérateur unaire ?comme son alias, afin d'éviter le besoin de parenthèses. Malheureusement, cette astuce n'est pas possible ici regexprcar il est nécessaire de lui donner l'argument supplémentaire fixed = True.

pinkfloydx33 Jan 24 2021 at 20:05

C # 114 octets

(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():"";}