Extrator de substring com palavras-chave específicas

Jan 07 2021

Desafio

O objetivo deste desafio é fazer uma função que receba uma string de entrada, uma palavra-chave inicial e uma palavra-chave final. O resultado extraído da saída é da (mas excluída) palavra-chave inicial fornecida para a palavra-chave final (mas excluída). A subcadeia de saída segue as regras abaixo.

  • Em todos os casos, os espaços iniciais / finais na subcadeia de saída devem ser removidos.

  • Se a palavra-chave start fornecida for uma string vazia, significa que a âncora está no início da string de entrada. Caso contrário, a primeira ocorrência da palavra-chave start fornecida é uma âncora inicial. Se não houver nenhuma ocorrência da palavra-chave inicial fornecida, a saída será uma string vazia.

  • Se a palavra-chave final fornecida for uma string vazia, significa que a âncora está no final da string de entrada. Caso contrário, a primeira ocorrência da palavra-chave final fornecida é uma âncora final. Se não houver nenhuma ocorrência da palavra-chave final fornecida, a saída será uma string vazia.

  • Se a localização da âncora inicial for posterior à localização da âncora final, ou uma parte da primeira ocorrência da palavra-chave inicial fornecida e uma parte da primeira ocorrência da palavra-chave final fornecida forem sobrepostas, a saída será uma string vazia.

Semelhante, mas diferente de Extrair uma string de uma determinada string , as âncoras de início e fim fornecidas são vários caracteres.

Aqui está uma implementação de referência não praticada em 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();
}

Exemplo de entrada e saída

O exemplo de entrada e saída está listado a seguir.

String de entrada Palavra-chave inicial Palavra-chave final Resultado
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "" (string vazia) "" (string vazia) "C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET"
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "" (string vazia) ".INTERNET" "C # foi desenvolvido por volta de 2000 pela Microsoft como parte de seu"
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "C #" "" (string vazia) "foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET"
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "C #" ".INTERNET" "foi desenvolvido por volta de 2000 pela Microsoft como parte de seu"
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" ".INTERNET" "" (string vazia) "iniciativa"
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "" (string vazia) "C #" "" (string vazia)
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" ".INTERNET" "C #" "" (string vazia)
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "ABC" "C #" "" (string vazia)
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" ".INTERNET" "XYZ" "" (string vazia)
"C # foi desenvolvido por volta de 2000 pela Microsoft como parte de sua iniciativa .NET" "ABC" "XYZ" "" (string vazia)

Regras

Este é o código de golfe . A resposta com o menor número de bytes vence.

Respostas

2 Adám Jan 07 2021 at 15:32

APL (Dyalog Extended) , 24 bytes ( SBCS )

Programa completo que solicita a matriz de [EndKeyword,StartKeyword,InputString]. Requer indexação baseada em 0.

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

Experimente online!

 solicitar entrada

 naquilo…

⌽¨@0 inverter todos os elementos que ocorrem no deslocamento 0

(... )/ reduza da direita usando a seguinte função tácita:

 indique com uma lista booleana todos os lugares onde o argumento esquerdo começa no argumento direito

⊣, acrescente o argumento esquerdo a isso

1⍳⍨ encontre o deslocamento do primeiro

⊢↓⍨ elimine todos os elementos principais do argumento certo

inverter (da próxima vez, faça isso a partir do final e, depois disso, reverta a ordem)

 divulgar o invólucro causado pela redução de uma matriz unidimensional para uma matriz 0-dimensional

⌂debd elete e nding (dianteira e traseira) b lanks

5 Arnauld Jan 07 2021 at 11:31

JavaScript (ES6),  80  75 bytes

Ele contém alguns caracteres não imprimíveis que escapam abaixo.

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

Experimente online!

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

Economizei 9 bytes graças ao movatica !!!
Economizei 2 bytes graças ao ovs !!!

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

Experimente online!

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

Experimente online!

Muito simples ...

1 vrintle Jan 07 2021 at 11:57

Ruby , 66 bytes

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

Experimente online!

Outro método sem o uso de regex,

Ruby , 72 bytes

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

Experimente online!

1 movatica Jan 08 2021 at 19:47

Python 3 , 100 85 bytes

Versão Regex, ainda não consegue vencer o algoritmo de fatiamento .

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

Experimente online!

1 Neil Jan 09 2021 at 19:04

Retina 0.8.2 , 60 bytes

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

Experimente online! Aceita a entrada como início, fim, string em linhas separadas, mas o link é para o conjunto de testes com cabeçalho que converte a string separada por vírgula, fim e início por conveniência. Explicação:

(.*)¶

Combine a palavra-chave inicial.

(.+)?¶

Opcionalmente, combine uma palavra-chave final não vazia.

.*?\1

Encontre a palavra-chave start o mais cedo possível na string, mais espaços opcionais.

 *(.*?) *

Combine um resultado o mais curto possível (de modo que a palavra-chave final seja encontrada o mais cedo possível na string), mas também apare os espaços ao redor dela.

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

Certifique-se de que a palavra-chave final ainda não tenha sido passada neste ponto.

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

Se a palavra-chave final estiver vazia, então corresponda apenas ao final da string;

|(.|¶)+

Se não foi possível corresponder a nada, exclua tudo.

$3

Mantenha o resultado desejado.

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

Experimente online!

1 GalenIvanov Jan 07 2021 at 15:30

Vermelho , 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]

Experimente online!

1 Davide Jan 10 2021 at 22:26

C (gcc) , 168 152 143 132 112 bytes

Um enorme -38 graças 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;}

Experimente online!

myjobistobehappy Jan 07 2021 at 13:05

JavaScript (ES6) 95 92 Bytes, sem Regex!

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

Como experimentar:

Abra o Console JavaScript do seu navegador e cole o seguinte.

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

Carvão , 41 bytes

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

Experimente online! O link é para a versão detalhada do código. Tome cuidado para incluir novas linhas suficientes na entrada, mesmo se uma das palavras-chave estiver vazia. Explicação:

≔⎇ζ…θ⌕θζθθ

Se a palavra-chave end não estiver vazia, trunque a string na primeira aparição. (Felizmente, CycleChoptrunca a string para ficar vazia se sua entrada for negativa.)

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

Se a palavra-chave start não estiver vazia, divida a string na palavra-chave, descarte o primeiro elemento e junte a string novamente. Isso resulta em uma string vazia se a palavra-chave start não aparecer na string.

≔⌕AEθ›ι ¹ε

Verifique se a string não possui espaços.

¿ε✂θ⌊ε⊕⌈ε

Em caso afirmativo, imprima do primeiro ao último sem espaço.

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

Experimente online!

Simples abordagem: achados delimitadora palavras usando regexpr(com argumento fixed = Tlamentar para garantir que a cadeia de texto não é interpretado como uma expressão regular), obtém o substring entre eles, e, em seguida, trimé a white sritmo de ambas as extremidades.

Como as funções nchare regexprsão usadas duas vezes, é mais curto definir apelidos de um caractere. No caso de nchar, podemos até redefinir o operador unário ?como seu alias, para evitar a necessidade de parênteses. Infelizmente, esse truque não é possível aqui, regexprdevido à necessidade de alimentá-lo com o 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():"";}