Trình trích xuất chuỗi con với các từ khóa cụ thể
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
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
⌂deb
d elete e nding (đầu và cuối) b lanks
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
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!
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...
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!
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!
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.
Ngôn ngữ Wolfram (Mathematica) , 93 byte
sStringTrim@StringTake[s,i=1;If[i*=-1;#=="",0,StringPosition[s,#][[1,i]]]-i&/@#]/._@_:>""&
Hãy thử nó trực tuyến!
Đỏ , 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!
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!
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')
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, CycleChop
cắ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.
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 f
ixed = T
hố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 substr
ing giữa chúng, và sau đó trim
là các w
Hite s
tốc độ từ cả hai đầu.
Vì các hàm nchar
và regexpr
mỗ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 regexpr
vì cần phải cung cấp cho nó đối số bổ sung f
ixed = T
rue.
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():"";}