특정 키워드가있는 하위 문자열 추출기

Jan 07 2021

도전

이 과제의 목표는 입력 문자열, 시작 키워드 및 종료 키워드를받는 함수를 만드는 것입니다. 추출 된 출력 결과는 지정된 시작 키워드에서 (그러나 제외됨) 종료 키워드까지입니다. 출력 하위 문자열은 아래와 같은 규칙을 따릅니다.

  • 모든 경우에 출력 하위 문자열의 선행 / 후행 공백을 제거해야합니다.

  • 주어진 시작 키워드가 빈 문자열이면 앵커가 입력 문자열의 시작에 있음을 의미합니다. 그렇지 않으면 주어진 시작 키워드의 첫 번째 발생이 시작 앵커입니다. 주어진 시작 키워드의 발생이 없으면 출력은 빈 문자열입니다.

  • 주어진 end 키워드가 빈 문자열이면 앵커가 입력 문자열의 끝에 있음을 의미합니다. 그렇지 않으면 주어진 end 키워드의 첫 번째 발생은 끝 앵커입니다. 주어진 end 키워드가 없으면 출력은 빈 문자열입니다.

  • 시작 앵커의 위치가 끝 앵커의 위치 이후이거나 지정된 시작 키워드의 첫 번째 발생 부분과 지정된 끝 키워드의 첫 번째 발생 부분이 겹치는 경우 출력은 빈 문자열입니다.

비슷하지만 주어진 문자열에서 문자열 추출과는 다르지만 지정된 시작 및 끝 앵커는 여러 문자입니다.

다음은 C #의 ungolfed 참조 구현입니다.

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

입력 및 출력 예

예제 입력 및 출력은 다음과 같습니다.

입력 문자열 시작 키워드 끝 키워드 산출
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ""(빈 문자열) ""(빈 문자열) "C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다."
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ""(빈 문자열) ".그물" "C #은 Microsoft에서 2000 년경에 개발되었습니다."
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." "씨#" ""(빈 문자열) "Microsoft는 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다."
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." "씨#" ".그물" "Microsoft의 일부로 2000 년경에 개발되었습니다."
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ".그물" ""(빈 문자열) "발의"
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ""(빈 문자열) "씨#" ""(빈 문자열)
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ".그물" "씨#" ""(빈 문자열)
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." "알파벳" "씨#" ""(빈 문자열)
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." ".그물" "XYZ" ""(빈 문자열)
"C #은 Microsoft가 .NET 이니셔티브의 일부로 2000 년경에 개발했습니다." "알파벳" "XYZ" ""(빈 문자열)

규칙

이것은 code-golf 입니다. 가장 적은 바이트의 대답이 이깁니다.

답변

2 Adám Jan 07 2021 at 15:32

APL (Dyalog 확장) , 24 바이트 ( SBCS )

의 배열을 묻는 전체 프로그램입니다 [EndKeyword,StartKeyword,InputString]. 0 기반 인덱싱이 필요합니다.

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

온라인으로 시도하십시오!

 입력 요청

 그것에…

⌽¨@0 오프셋 0에서 발생하는 모든 요소 반전

()/ 다음 암묵적 기능을 사용하여 오른쪽에서 줄이십시오.

 왼쪽 인수가 오른쪽 인수에서 시작하는 모든 위치를 부울 목록으로 표시

⊣, 그 앞에 왼쪽 인수를 추가

1⍳⍨ 처음 1의 오프셋을 찾으십시오.

⊢↓⍨ 오른쪽 인수에서 많은 선행 요소를 삭제

역순 (다음 번에 끝부터이 작업을 수행 한 후 순서를 되돌립니다.)

 1 차원 어레이에서 0 차원 어레이로의 축소로 인한 인클로저 공개

⌂debd elete e nding (선행 및 후행) b lanks

5 Arnauld Jan 07 2021 at 11:31

JavaScript (ES6),  80  75 바이트

아래에 이스케이프 처리 된 인쇄 할 수없는 문자가 포함되어 있습니다.

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

온라인으로 시도하십시오!

댓글 작성

(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 바이트

movatica 덕분에 9 바이트 절약 !!! ovs
덕분에 2 바이트 절약 !!!

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

온라인으로 시도하십시오!

1 tsh Jan 07 2021 at 13:12

JavaScript (Node.js) , 74 바이트

(s,a,b)=>s.substr(p=(s+a).indexOf(a)+a.length,b?s.indexOf(b)-p:1/0).trim()

온라인으로 시도하십시오!

아주 간단합니다 ...

1 vrintle Jan 07 2021 at 11:57

Ruby , 66 바이트

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

온라인으로 시도하십시오!

정규식을 사용하지 않는 또 다른 방법은

Ruby , 72 바이트

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

온라인으로 시도하십시오!

1 movatica Jan 08 2021 at 19:47

Python 3 , 100 85 바이트

정규식 버전은 여전히 슬라이싱 알고리즘을 이길 수 없습니다 .

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

온라인으로 시도하십시오!

1 Neil Jan 09 2021 at 19:04

Retina 0.8.2 , 60 바이트

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

온라인으로 시도하십시오! 별도의 줄에 시작, 끝, 문자열로 입력을 받지만 링크는 편의를 위해 쉼표로 구분 된 문자열, 끝, 시작에서 변환하는 헤더가있는 테스트 스위트입니다. 설명:

(.*)¶

시작 키워드와 일치합니다.

(.+)?¶

선택적으로 비어 있지 않은 끝 키워드와 일치합니다.

.*?\1

문자열에서 가능한 한 빨리 시작 키워드와 선택적 공백을 찾으십시오.

 *(.*?) *

가능한 한 짧은 결과를 일치시키고 (문자열에서 가능한 한 빨리 end 키워드를 찾을 수 있도록) 그 주변의 공백도 잘라냅니다.

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

이 시점에서 end 키워드가 아직 전달되지 않았는지 확인하십시오.

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

종료 키워드가 비어 있으면 문자열의 끝에서만 일치하고 그렇지 않으면 종료 키워드와 나머지 문자열과 일치합니다.

|(.|¶)+

일치하는 항목이 없으면 모두 삭제하십시오.

$3

원하는 결과를 유지하십시오.

1 att Jan 07 2021 at 13:42

Wolfram 언어 (Mathematica) , 93 바이트

sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&

온라인으로 시도하십시오!

1 GalenIvanov Jan 07 2021 at 15:30

빨간색 , 90 바이트

func[t s e][p:""if""<> s[append s" "]if e =""[e:[end]]parse t[thru s copy p to[opt" "e]]p]

온라인으로 시도하십시오!

1 Davide Jan 10 2021 at 22:26

C (GCC) , 168 (152) 143 132 112 바이트

@ceilingcat 덕분에 엄청난 -38

#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;}

온라인으로 시도하십시오!

myjobistobehappy Jan 07 2021 at 13:05

JavaScript (ES6) 95 92 바이트, 정규식 없음!

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

그것을 시도하는 방법 :

브라우저의 JavaScript 콘솔을 열고 다음을 붙여 넣으십시오.

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

목탄 , 41 바이트

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

온라인으로 시도하십시오! 링크는 자세한 코드 버전입니다. 키워드 중 하나가 비어 있더라도 입력에 충분한 줄 바꿈을 포함하도록주의하십시오. 설명:

≔⎇ζ…θ⌕θζθθ

end 키워드가 비어 있지 않으면 처음 나타나는 문자열을 자릅니다. (다행히도 CycleChop입력이 음수이면 문자열을 비워 둡니다.)

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

시작 키워드가 비어 있지 않으면 키워드에서 문자열을 분할하고 첫 번째 요소를 버리고 문자열을 다시 결합하십시오. 시작 키워드가 문자열에 나타나지 않으면 빈 문자열이됩니다.

≔⌕AEθ›ι ¹ε

문자열에 공백이 없는지 확인하십시오.

¿ε✂θ⌊ε⊕⌈ε

그렇다면 공백이 아닌 첫 번째부터 마지막까지 인쇄하십시오.

DominicvanEssen Jan 11 2021 at 06:31

R , 111 바이트

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

온라인으로 시도하십시오!

간단한 방법 : 사용하여 단어를 경계 발견은 regexpr(인수 fixed =이 T텍스트 문자열은 정규식으로 해석되지 않도록 후회)에 도착 substr그들 사이 ING를, 다음 trim의 S w하이트 s양쪽 끝에서 속도.

nchar및 함수 regexpr는 각각 두 번 사용 되기 때문에 단일 문자 별칭을 정의하는 것이 더 짧습니다. 의 경우 nchar단항 연산자 ?를 별칭으로 다시 정의 할 수도 있으므로 괄호가 필요하지 않습니다. 불행히도이 트릭은 regexpr추가 인수 fixed = True 를 제공해야하기 때문에 여기서는 불가능합니다 .

pinkfloydx33 Jan 24 2021 at 20:05

C # 114 바이트

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