Extrator de substring com palavras-chave específicas
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
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
⌂deb
d elete e nding (dianteira e traseira) b lanks
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
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!
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 ...
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!
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!
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.
Wolfram Language (Mathematica) , 93 bytes
sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&
Experimente online!
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!
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!
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')
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, CycleChop
trunca 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.
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 f
ixed = T
lamentar para garantir que a cadeia de texto não é interpretado como uma expressão regular), obtém o substr
ing entre eles, e, em seguida, trim
é a w
hite s
ritmo de ambas as extremidades.
Como as funções nchar
e regexpr
sã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, regexpr
devido à necessidade de alimentá-lo com o 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():"";}