Extractor de subcadena con palabras clave específicas
Desafío
El objetivo de este desafío es crear una función que tome una cadena de entrada, una palabra clave inicial y una palabra clave final. El resultado extraído es de (pero excluida) la palabra clave inicial dada a (pero excluida) palabra clave final. La subcadena de salida sigue las reglas siguientes.
En todos los casos, los espacios iniciales / finales en la subcadena de salida deben eliminarse.
Si la palabra clave de inicio dada es una cadena vacía, significa que el ancla está al comienzo de la cadena de entrada. De lo contrario, la primera aparición de la palabra clave de inicio dada es un ancla de inicio. Si no hay ninguna ocurrencia de la palabra clave de inicio dada, la salida es una cadena vacía.
Si la palabra clave final dada es una cadena vacía, significa que el ancla está al final de la cadena de entrada. De lo contrario, la primera aparición de la palabra clave final dada es un ancla final. Si no hay ninguna ocurrencia de la palabra clave final dada, la salida es una cadena vacía.
Si la ubicación del ancla inicial es posterior a la ubicación del ancla final, o una parte de la primera aparición de la palabra clave inicial dada y una parte de la primera aparición de la palabra clave final dada se superponen, la salida es una cadena vacía.
Similar pero diferente a Extraer una cadena de una cadena dada , los anclajes iniciales y finales dados son múltiples caracteres.
Aquí hay una implementación de referencia sin golf 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();
}
Ejemplo de entrada y salida
La entrada y salida de ejemplo se enumeran a continuación.
Cadena de entrada | Iniciar palabra clave | Palabra clave final | Salida |
---|---|---|---|
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ""(cuerda vacía) | ""(cuerda vacía) | "C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ""(cuerda vacía) | ".RED" | "C # fue desarrollado alrededor de 2000 por Microsoft como parte de su" |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | "C#" | ""(cuerda vacía) | "fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | "C#" | ".RED" | "fue desarrollado alrededor de 2000 por Microsoft como parte de su" |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ".RED" | ""(cuerda vacía) | "iniciativa" |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ""(cuerda vacía) | "C#" | ""(cuerda vacía) |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ".RED" | "C#" | ""(cuerda vacía) |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | "A B C" | "C#" | ""(cuerda vacía) |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | ".RED" | "XYZ" | ""(cuerda vacía) |
"C # fue desarrollado alrededor del año 2000 por Microsoft como parte de su iniciativa .NET" | "A B C" | "XYZ" | ""(cuerda vacía) |
Reglas
Esto es código de golf . La respuesta con la menor cantidad de bytes gana.
Respuestas
APL (Dyalog Extended) , 24 bytes ( SBCS )
Programa completo que solicita una variedad de archivos [EndKeyword,StartKeyword,InputString]
. Requiere indexación basada en 0.
⌂deb⊃(⌽⊢↓⍨1⍳⍨⊣,⍷)/⌽¨@0⊢⎕
¡Pruébelo en línea!
⎕
pedir entrada
⊢
en ese…
⌽¨@0
invertir todos los elementos que ocurren en el desplazamiento 0
(
… )/
Reducir desde la derecha usando la siguiente función tácita:
⍷
indicar con una lista booleana todos los lugares donde comienza el argumento de la izquierda en el argumento de la derecha
⊣,
anteponer el argumento de la izquierda a eso
1⍳⍨
encontrar el desplazamiento del primer 1
⊢↓⍨
eliminar tantos elementos principales del argumento correcto
⌽
revertir (la próxima vez, haz esto desde el final y luego revierte el orden)
⊃
divulgar el recinto causado por la reducción de una matriz unidimensional a una matriz de 0 dimensiones
⌂deb
d elete e nding ( inicial y final) b lanks
JavaScript (ES6), 80 75 bytes
Esto contiene algunos caracteres no imprimibles que se escapan a continuación.
(s,a,b)=>s.replace(b||/$/,"").replace(a,"").match(/ *(.*?) *|$/)[1]||""
¡Pruébelo en línea!
Comentado
(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 bytes
Guardado 9 bytes gracias a movatica !!!
Guardado 2 bytes gracias a ovs !!!
lambda s,a,b:s[s.find(a):(b in s)*s.find(b)if b else None][len(a):].strip()
¡Pruébelo en línea!
JavaScript (Node.js) , 74 bytes
(s,a,b)=>s.substr(p=(s+a).indexOf(a)+a.length,b?s.indexOf(b)-p:1/0).trim()
¡Pruébelo en línea!
Bastante sencillo...
Rubí , 66 bytes
->w,s,e,r=Regexp{"#{w[/#{r.quote s}\K.+(?=#{r.quote e})/]}".strip}
¡Pruébelo en línea!
Otro método sin el uso de expresiones regulares,
Rubí , 72 bytes
->w,s,e{"#{w[((w+s).index(s)+s.size rescue 0)...w.rindex(e)||0]}".strip}
¡Pruébelo en línea!
Python 3 , 100 85 bytes
Versión Regex, todavía no puede vencer al algoritmo de corte .
from re import*
r=escape
f=lambda s,b,e:(search(r(b)+'(.+)'+r(e),s)or' ')[1].strip()
¡Pruébelo en línea!
Retina 0.8.2 , 60 bytes
(.*)¶(.+)?¶.*?\1 *(.*?) *(?<!(?=\2).*)(?(2)\2.*|$)|(.|¶)+ $3
¡Pruébelo en línea! Toma la entrada como inicio, fin, cadena en líneas separadas, pero el enlace es para probar el conjunto con encabezado que convierte de una cadena separada por comas, final, comienzo por conveniencia. Explicación:
(.*)¶
Coincide con la palabra clave de inicio.
(.+)?¶
Opcionalmente, haga coincidir una palabra clave final que no esté vacía.
.*?\1
Busque la palabra clave de inicio lo antes posible en la cadena, más espacios opcionales.
*(.*?) *
Haga coincidir un resultado lo más corto posible (de modo que la palabra clave final se encuentre lo antes posible en la cadena) pero también recorte los espacios a su alrededor.
(?<!(?=\2).*)
Asegúrese de que la palabra clave final no se haya pasado ya en este momento.
(?(2)\2.*|$)
Si la palabra clave final estaba vacía, solo debe coincidir al final de la cadena; de lo contrario, haga coincidir la palabra clave final y el resto de la cadena.
|(.|¶)+
Si no fue posible hacer coincidir nada, elimine todo.
$3
Mantenga el resultado deseado.
Wolfram Language (Mathematica) , 93 bytes
sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&
¡Pruébelo en línea!
Rojo , 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]
¡Pruébelo en línea!
C (gcc) , 168 152 143 132 112 bytes
Un enorme -38 gracias 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;}
¡Pruébelo en línea!
JavaScript (ES6) 95 92 Bytes, ¡Sin expresiones regulares!
(i,s,e,t=i.indexOf(s),r=i.lastIndexOf(e))=>t!=-1&r!=-1?(i.substring(t+s.length,r)).trim():''
Cómo probarlo:
Abra la consola JavaScript de su navegador y pegue lo siguiente.
((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')
Carbón , 41 bytes
≔⎇ζ…θ⌕θζθθ≔⎇η⪫Φ⪪θηκηθθ≔⌕AEθ›ι ¹ε¿ε✂θ⌊ε⊕⌈ε
¡Pruébelo en línea! El enlace corresponde a una versión detallada del código. Tenga cuidado de incluir suficientes nuevas líneas en la entrada, incluso si una de las palabras clave está vacía. Explicación:
≔⎇ζ…θ⌕θζθθ
Si la palabra clave final no está vacía, trunque la cadena en su primera aparición. (Afortunadamente, CycleChop
trunca la cadena para que quede vacía si su entrada es negativa).
≔⎇η⪫Φ⪪θηκηθθ
Si la palabra clave de inicio no está vacía, divida la cadena en la palabra clave, descarte el primer elemento y vuelva a unir la cadena. Esto da como resultado una cadena vacía si la palabra clave de inicio no aparece en la cadena.
≔⌕AEθ›ι ¹ε
Compruebe si la cadena no tiene espacios.
¿ε✂θ⌊ε⊕⌈ε
Si es así, imprima desde el primero hasta el último sin espacio.
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)))
¡Pruébelo en línea!
Sencillas de aproximación: hallazgos que limitan el uso de palabras regexpr
(con el argumento f
ixed = T
rue para asegurar que la cadena de texto no se interpreta como una expresión regular), obtiene el substr
ing entre ellos, y luego trim
s del w
hite s
ritmo de ambos extremos.
Dado que las funciones nchar
y regexpr
se utilizan dos veces, es más corto definir alias de un solo carácter. En el caso de nchar
, incluso podemos redefinir el operador unario ?
como su alias, para evitar la necesidad de usar paréntesis. Desafortunadamente, este truco no es posible aquí regexpr
debido a la necesidad de alimentarlo con el argumento adicional f
ixed = T
rue.
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():"";}