Estrattore di sottostringa con parole chiave specifiche
Sfida
L'obiettivo di questa sfida è creare una funzione che accetti una stringa di input, una parola chiave iniziale e una parola chiave finale. Il risultato dell'output estratto proviene (ma escluso) dalla parola chiave iniziale data alla parola chiave end (ma esclusa). La sottostringa di output segue le regole come di seguito.
In tutti i casi, gli spazi iniziali / finali nella sottostringa di output dovrebbero essere rimossi.
Se la parola chiave di inizio data è una stringa vuota, significa che l'ancora si trova all'inizio della stringa di input. Altrimenti, la prima occorrenza della parola chiave di inizio data è un'ancora di inizio. Se non è presente alcuna occorrenza della parola chiave iniziale specificata, l'output è una stringa vuota.
Se la parola chiave end specificata è una stringa vuota, significa che l'ancora si trova alla fine della stringa di input. Altrimenti, la prima occorrenza della parola chiave end specificata è un'ancora di fine. Se non è presente alcuna occorrenza della parola chiave end specificata, l'output è una stringa vuota.
Se la posizione dell'ancoraggio iniziale è successiva alla posizione dell'ancoraggio finale, o una parte della prima occorrenza della parola chiave iniziale data e una parte della prima occorrenza della parola chiave finale specificata sono sovrapposte, l'output è una stringa vuota.
Simile ma diverso da Estrai una stringa da una determinata stringa , le ancore di inizio e fine fornite sono più caratteri.
Ecco un'implementazione di riferimento ungolfed 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();
}
Input e output di esempio
L'input e l'output di esempio sono elencati di seguito.
Stringa di input | Avvia parola chiave | Fine parola chiave | Produzione |
---|---|---|---|
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ""(stringa vuota) | ""(stringa vuota) | "C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ""(stringa vuota) | ".NETTO" | "C # è stato sviluppato intorno al 2000 da Microsoft come parte del suo" |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | "C #" | ""(stringa vuota) | "è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | "C #" | ".NETTO" | "è stato sviluppato intorno al 2000 da Microsoft come parte del suo" |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ".NETTO" | ""(stringa vuota) | "iniziativa" |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ""(stringa vuota) | "C #" | ""(stringa vuota) |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ".NETTO" | "C #" | ""(stringa vuota) |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | "ABC" | "C #" | ""(stringa vuota) |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | ".NETTO" | "XYZ" | ""(stringa vuota) |
"C # è stato sviluppato intorno al 2000 da Microsoft come parte della sua iniziativa .NET" | "ABC" | "XYZ" | ""(stringa vuota) |
Regole
Questo è il golf in codice . La risposta con il minor numero di byte vince.
Risposte
APL (Dyalog Extended) , 24 byte ( SBCS )
Programma completo che richiede un array di file [EndKeyword,StartKeyword,InputString]
. Richiede un'indicizzazione basata su 0.
⌂deb⊃(⌽⊢↓⍨1⍳⍨⊣,⍷)/⌽¨@0⊢⎕
Provalo online!
⎕
richiesta di input
⊢
su quello…
⌽¨@0
inverte tutti gli elementi che si verificano all'offset 0
(
... )/
ridurre da destra utilizzando la seguente funzione tacita:
⍷
indicare con un elenco booleano tutti i punti in cui l'argomento di sinistra inizia nell'argomento di destra
⊣,
anteponi l'argomento a sinistra a quello
1⍳⍨
trova l'offset del primo 1
⊢↓⍨
lascia cadere tanti elementi principali dall'argomento giusto
⌽
inverso (la prossima volta, fallo dalla fine e dopo, ripristina l'ordine)
⊃
divulgare l'involucro causato dalla riduzione da una matrice unidimensionale a una matrice 0-dimensionale
⌂deb
d elete e reperto (iniziali e finali) b Lanks
JavaScript (ES6), 80 75 byte
Questo contiene alcuni caratteri non stampabili di cui sotto.
(s,a,b)=>s.replace(b||/$/,"").replace(a,"").match(/ *(.*?) *|$/)[1]||""
Provalo online!
Commentato
(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 byte
Salvati 9 byte grazie a movatica !!!
Salvato 2 byte grazie a ovs !!!
lambda s,a,b:s[s.find(a):(b in s)*s.find(b)if b else None][len(a):].strip()
Provalo online!
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()
Provalo online!
Abbastanza semplice ...
Ruby , 66 byte
->w,s,e,r=Regexp{"#{w[/#{r.quote s}\K.+(?=#{r.quote e})/]}".strip}
Provalo online!
Un altro metodo senza l'uso di regex,
Ruby , 72 byte
->w,s,e{"#{w[((w+s).index(s)+s.size rescue 0)...w.rindex(e)||0]}".strip}
Provalo online!
Python 3 , 100 85 byte
Versione Regex, ancora non può battere l' algoritmo di slicing .
from re import*
r=escape
f=lambda s,b,e:(search(r(b)+'(.+)'+r(e),s)or' ')[1].strip()
Provalo online!
Retina 0.8.2 , 60 byte
(.*)¶(.+)?¶.*?\1 *(.*?) *(?<!(?=\2).*)(?(2)\2.*|$)|(.|¶)+ $3
Provalo online! Accetta l'input come inizio, fine, stringa su righe separate ma il collegamento è alla suite di test con intestazione che converte da stringa separata da virgola, fine, inizio per comodità. Spiegazione:
(.*)¶
Trova la parola chiave iniziale.
(.+)?¶
Facoltativamente, abbina una parola chiave finale non vuota.
.*?\1
Trova la parola chiave iniziale il prima possibile nella stringa, più gli spazi facoltativi.
*(.*?) *
Trova il risultato il più breve possibile (in modo che la parola chiave end venga trovata il prima possibile nella stringa) ma ritaglia anche gli spazi attorno ad essa.
(?<!(?=\2).*)
Assicurati che la parola chiave end non sia già stata passata a questo punto.
(?(2)\2.*|$)
Se la parola chiave end era vuota, corrisponde solo alla fine della stringa, altrimenti corrisponde alla parola chiave end e al resto della stringa.
|(.|¶)+
Se non è stato possibile trovare una corrispondenza, elimina tutto.
$3
Mantieni il risultato desiderato.
Wolfram Language (Mathematica) , 93 byte
sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&
Provalo online!
Rosso , 90 byte
func[t s e][p:""if""<> s[append s" "]if e =""[e:[end]]parse t[thru s copy p to[opt" "e]]p]
Provalo online!
C (gcc) , 168 152 143 132 112 byte
Un enorme -38 grazie a @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;}
Provalo online!
JavaScript (ES6) 95 92 byte, nessuna espressione regolare!
(i,s,e,t=i.indexOf(s),r=i.lastIndexOf(e))=>t!=-1&r!=-1?(i.substring(t+s.length,r)).trim():''
Come provarlo:
Apri la console JavaScript del tuo browser e incolla quanto segue.
((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')
Carboncino , 41 byte
≔⎇ζ…θ⌕θζθθ≔⎇η⪫Φ⪪θηκηθθ≔⌕AEθ›ι ¹ε¿ε✂θ⌊ε⊕⌈ε
Provalo online! Il collegamento è alla versione dettagliata del codice. Assicurati di includere un numero sufficiente di nuove righe nell'input anche se una delle parole chiave è vuota. Spiegazione:
≔⎇ζ…θ⌕θζθθ
Se la parola chiave end non è vuota, tronca la stringa alla prima comparsa. (Fortunatamente CycleChop
tronca la stringa a vuoto se il suo input è negativo.)
≔⎇η⪫Φ⪪θηκηθθ
Se la parola chiave di inizio non è vuota, dividere la stringa sulla parola chiave, eliminare il primo elemento e unire nuovamente la stringa. Ciò si traduce in una stringa vuota se la parola chiave start non viene visualizzata nella stringa.
≔⌕AEθ›ι ¹ε
Controlla se la stringa contiene non spazi.
¿ε✂θ⌊ε⊕⌈ε
In tal caso, stampa dal primo all'ultimo non spazio.
R , 111 byte
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)))
Provalo online!
Approccio diretto: trova le parole che delimitano usando regexpr
(con argomento f
ixed = T
rue per garantire che la stringa di testo non sia interpretata come regex), ottiene l' substr
intervallo tra di loro e quindi trim
s il ritmo w
hite s
da entrambe le estremità.
Poiché le funzioni nchar
e regexpr
vengono utilizzate due volte ciascuna, è più breve definire alias a carattere singolo. Nel caso di nchar
, possiamo anche ridefinire l'operatore unario ?
come suo alias, in modo da evitare la necessità di parentesi. Sfortunatamente, questo trucco non è possibile qui a regexpr
causa della necessità di alimentarlo con l'argomento aggiuntivo f
ixed = T
rue.
C # 114 byte
(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():"";}