Extracteur de sous-chaînes avec des mots clés spécifiques
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
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
⌂deb
d elete e Nding (avant et arrière) b Lanks
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
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!
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...
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!
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!
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é.
Wolfram Language (Mathematica) , 93 octets
sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&
Essayez-le en ligne!
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!
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!
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')
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, CycleChop
tronque 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.
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 f
MMOBILISATIONS = T
rue 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 substr
entre elles, puis trim
s le w
Hite s
rythme des deux extrémités.
Puisque les fonctions nchar
et regexpr
sont 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 regexpr
car il est nécessaire de lui donner l'argument supplémentaire f
ixed = T
rue.
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():"";}