Extractor de subcadena con palabras clave específicas

Jan 07 2021

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

2 Adám Jan 07 2021 at 15:32

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

⌂debd elete e nding ( inicial y final) b lanks

5 Arnauld Jan 07 2021 at 11:31

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
3 Noodle9 Jan 08 2021 at 19:19

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!

1 tsh Jan 07 2021 at 13:12

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

1 vrintle Jan 07 2021 at 11:57

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!

1 movatica Jan 08 2021 at 19:47

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!

1 Neil Jan 09 2021 at 19:04

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.

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&/@#]/._@_:>""&

¡Pruébelo en línea!

1 GalenIvanov Jan 07 2021 at 15:30

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!

1 Davide Jan 10 2021 at 22:26

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!

myjobistobehappy Jan 07 2021 at 13:05

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')
Neil Jan 09 2021 at 22:40

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, CycleChoptrunca 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.

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

¡Pruébelo en línea!

Sencillas de aproximación: hallazgos que limitan el uso de palabras regexpr(con el argumento fixed = True para asegurar que la cadena de texto no se interpreta como una expresión regular), obtiene el substring entre ellos, y luego trims del white sritmo de ambos extremos.

Dado que las funciones nchary regexprse 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í regexprdebido a la necesidad de alimentarlo con el argumento adicional fixed = True.

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