Trình trích xuất chuỗi con với các từ khóa cụ thể

Jan 07 2021

Thử thách

Mục tiêu của thử thách này là tạo một hàm nhận một chuỗi đầu vào, một từ khóa bắt đầu và một từ khóa kết thúc. Kết quả được trích xuất đầu ra là từ (nhưng bị loại trừ) từ khóa bắt đầu đã cho đến (nhưng bị loại trừ) từ khóa kết thúc. Chuỗi con đầu ra tuân theo các quy tắc như bên dưới.

  • Trong mọi trường hợp, các khoảng trống ở đầu / cuối trong chuỗi con đầu ra phải được loại bỏ.

  • Nếu từ khóa bắt đầu đã cho là một chuỗi trống, điều đó có nghĩa là mỏ neo ở đầu chuỗi đầu vào. Nếu không, lần xuất hiện đầu tiên của từ khóa bắt đầu đã cho là một ký tự bắt đầu. Nếu không có bất kỳ sự xuất hiện nào của từ khóa bắt đầu đã cho, đầu ra là một chuỗi trống.

  • Nếu từ khóa kết thúc đã cho là một chuỗi trống, điều đó có nghĩa là mỏ neo ở cuối chuỗi đầu vào. Nếu không, lần xuất hiện đầu tiên của từ khóa kết thúc đã cho là một ký tự neo kết thúc. Nếu không có bất kỳ sự xuất hiện nào của từ khóa kết thúc đã cho, kết quả đầu ra là một chuỗi trống.

  • Nếu vị trí của neo bắt đầu nằm sau vị trí của neo kết thúc hoặc một phần của lần xuất hiện đầu tiên của từ khóa bắt đầu đã cho và một phần của lần xuất hiện đầu tiên của từ khóa kết thúc đã cho bị chồng chéo, thì kết quả đầu ra là một chuỗi trống.

Tương tự nhưng khác với Trích xuất một chuỗi từ một chuỗi nhất định , các neo bắt đầu và kết thúc đã cho là nhiều ký tự.

Đây là một triển khai tham chiếu không có nguồn gốc trong 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();
}

Ví dụ đầu vào và đầu ra

Ví dụ đầu vào và đầu ra được liệt kê như dưới đây.

Chuỗi đầu vào Bắt đầu từ khóa Từ khoá Kết thúc Đầu ra
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "" (chuỗi trống) "" (chuỗi trống) "C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET"
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "" (chuỗi trống) ".MẠNG LƯỚI" "C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của nó"
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "C #" "" (chuỗi trống) "được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET"
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "C #" ".MẠNG LƯỚI" "được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của"
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" ".MẠNG LƯỚI" "" (chuỗi trống) "sáng kiến"
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "" (chuỗi trống) "C #" "" (chuỗi trống)
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" ".MẠNG LƯỚI" "C #" "" (chuỗi trống)
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "ABC" "C #" "" (chuỗi trống)
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" ".MẠNG LƯỚI" "XYZ" "" (chuỗi trống)
"C # được phát triển vào khoảng năm 2000 bởi Microsoft như một phần của sáng kiến ​​.NET" "ABC" "XYZ" "" (chuỗi trống)

Quy tắc

Đây là mã-gôn . Câu trả lời có ít byte nhất sẽ thắng.

Trả lời

2 Adám Jan 07 2021 at 15:32

APL (Dyalog Extended) , 24 byte ( SBCS )

Chương trình đầy đủ nhắc nhở mảng [EndKeyword,StartKeyword,InputString]. Yêu cầu lập chỉ mục dựa trên 0.

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

Hãy thử nó trực tuyến!

 nhắc nhập

 trong vấn đề này…

⌽¨@0 đảo ngược tất cả các phần tử xảy ra ở độ lệch 0

()/ Giảm từ bên phải bằng cách sử dụng hàm ngầm sau:

 chỉ ra với một danh sách Boolean tất cả các vị trí mà đối số bên trái bắt đầu trong đối số bên phải

⊣, thêm đối số bên trái vào đó

1⍳⍨ tìm phần bù của 1 đầu tiên

⊢↓⍨ loại bỏ nhiều yếu tố hàng đầu khỏi đối số đúng

đảo ngược (lần sau, làm điều này từ cuối và sau đó, hoàn nguyên thứ tự)

 tiết lộ sự bao vây gây ra bởi việc giảm từ mảng 1 chiều thành mảng 0 chiều

⌂debd elete e nding (đầu và cuối) b lanks

5 Arnauld Jan 07 2021 at 11:31

JavaScript (ES6),  80  75 byte

Điều này chứa một số ký tự không thể in được ẩn bên dưới.

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

Hãy thử nó trực tuyến!

Đã nhận xét

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

Đã lưu 9 byte nhờ movatica !!!
Đã lưu 2 byte nhờ ovs !!!

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

Hãy thử nó trực tuyến!

1 tsh Jan 07 2021 at 13:12

JavaScript (Node.js) , 74 byte

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

Hãy thử nó trực tuyến!

Khá đơn giản...

1 vrintle Jan 07 2021 at 11:57

Ruby , 66 byte

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

Hãy thử nó trực tuyến!

Một phương pháp khác không sử dụng regex,

Ruby , 72 byte

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

Hãy thử nó trực tuyến!

1 movatica Jan 08 2021 at 19:47

Python 3 , 100 85 byte

Phiên bản Regex, vẫn không thể đánh bại thuật toán cắt .

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

Hãy thử nó trực tuyến!

1 Neil Jan 09 2021 at 19:04

Retina 0.8.2 , 60 byte

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

Hãy thử nó trực tuyến! Nhận đầu vào là bắt đầu, kết thúc, chuỗi trên các dòng riêng biệt nhưng liên kết là để kiểm tra bộ với tiêu đề chuyển đổi từ chuỗi được phân tách bằng dấu phẩy, kết thúc, bắt đầu để thuận tiện. Giải trình:

(.*)¶

Khớp với từ khóa bắt đầu.

(.+)?¶

Đối sánh tùy chọn với từ khóa kết thúc không trống.

.*?\1

Tìm từ khóa bắt đầu càng sớm càng tốt trong chuỗi, cộng với khoảng trắng tùy chọn.

 *(.*?) *

So khớp kết quả càng ngắn càng tốt (để từ khóa kết thúc được tìm thấy sớm nhất có thể trong chuỗi) nhưng cũng cắt bớt khoảng trống xung quanh từ khóa đó.

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

Đảm bảo rằng từ khóa kết thúc chưa được chuyển vào thời điểm này.

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

Nếu từ khóa kết thúc trống thì chỉ đối sánh ở cuối chuỗi, nếu không thì đối sánh với từ khóa kết thúc và phần còn lại của chuỗi.

|(.|¶)+

Nếu không thể khớp bất kỳ thứ gì, hãy xóa mọi thứ.

$3

Giữ kết quả mong muốn.

1 att Jan 07 2021 at 13:42

Ngôn ngữ Wolfram (Mathematica) , 93 byte

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

Hãy thử nó trực tuyến!

1 GalenIvanov Jan 07 2021 at 15:30

Đỏ , 90 byte

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

Hãy thử nó trực tuyến!

1 Davide Jan 10 2021 at 22:26

C (gcc) , 168 152 143 132 112 byte

Một -38 to lớn nhờ @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;}

Hãy thử nó trực tuyến!

myjobistobehappy Jan 07 2021 at 13:05

JavaScript (ES6) 95 92 Byte, Không có Regex!

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

Làm thế nào để thử nó:

Mở Bảng điều khiển JavaScript của trình duyệt của bạn và dán nội dung sau.

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

Than củi , 41 byte

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

Hãy thử nó trực tuyến! Liên kết là phiên bản dài của mã. Hãy cẩn thận đưa đủ dòng mới vào đầu vào ngay cả khi một trong các từ khóa trống. Giải trình:

≔⎇ζ…θ⌕θζθθ

Nếu từ khóa end không trống thì hãy cắt ngắn chuỗi ở lần xuất hiện đầu tiên. (May mắn thay, CycleChopcắt ngắn chuỗi để trống nếu đầu vào của nó là số âm.)

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

Nếu từ khóa bắt đầu không trống thì hãy tách chuỗi trên từ khóa, loại bỏ phần tử đầu tiên và nối lại chuỗi. Điều này dẫn đến một chuỗi trống nếu từ khóa bắt đầu không xuất hiện trong chuỗi.

≔⌕AEθ›ι ¹ε

Kiểm tra xem chuỗi có bất kỳ dấu cách nào không.

¿ε✂θ⌊ε⊕⌈ε

Nếu vậy thì in từ đầu tiên đến cuối cùng không dấu cách.

DominicvanEssen Jan 11 2021 at 06:31

R , 111 byte

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

Hãy thử nó trực tuyến!

Đơn giản phương pháp: phát hiện bounding từ sử dụng regexpr(với lập luận fixed = Thối tiếc để đảm bảo rằng các chuỗi văn bản không được hiểu như là một regex), nhận được substring giữa chúng, và sau đó trimlà các wHite stốc độ từ cả hai đầu.

Vì các hàm ncharregexprmỗi hàm được sử dụng hai lần nên việc xác định bí danh một ký tự sẽ ngắn hơn. Trong trường hợp của nchar, chúng tôi thậm chí có thể xác định lại toán tử một ngôi ?làm bí danh của nó, để chúng tôi tránh sự cần thiết của dấu ngoặc đơn. Thật không may, thủ thuật này không thể thực hiện được ở đây regexprvì cần phải cung cấp cho nó đối số bổ sung fixed = True.

pinkfloydx33 Jan 24 2021 at 20:05

C # 114 byte

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