Средство извлечения подстроки с определенными ключевыми словами

Jan 07 2021

Вызов

Цель этой задачи - создать функцию, которая принимает входную строку, ключевое слово start и ключевое слово end. Вывод извлечен результат от (но исключенного) заданного ключевого слова start до (но исключенного) ключевого слова end. Выходная подстрока подчиняется следующим правилам.

  • Во всех случаях следует удалить начальные / конечные пробелы в выходной подстроке.

  • Если заданное ключевое слово start является пустой строкой, это означает, что привязка находится в начале входной строки. В противном случае первое вхождение данного ключевого слова start является начальным якорем. Если заданное ключевое слово start не встречается, выводом будет пустая строка.

  • Если заданное ключевое слово end является пустой строкой, это означает, что привязка находится в конце входной строки. В противном случае первое вхождение данного ключевого слова end является конечной привязкой. Если заданное ключевое слово end не встречается, на выходе будет пустая строка.

  • Если местоположение начального якоря находится после местоположения конечного якоря, или если часть первого вхождения заданного ключевого слова начала и часть первого вхождения данного ключевого слова конца перекрываются, выводом является пустая строка.

Подобно извлечению строки из заданной строки , но отличается от нее , указанные начальная и конечная привязки состоят из нескольких символов.

Вот беззащитная эталонная реализация на 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();
}

Пример ввода и вывода

Примеры ввода и вывода перечислены ниже.

Строка ввода Начать ключевое слово Конец ключевого слова Вывод
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ""(пустой строки) ""(пустой строки) «C # был разработан Microsoft около 2000 года в рамках инициативы .NET»
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ""(пустой строки) ".СЕТЬ" «C # был разработан Microsoft около 2000 года как часть своего проекта»
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» "C #" ""(пустой строки) "был разработан Microsoft около 2000 года в рамках инициативы .NET"
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» "C #" ".СЕТЬ" "был разработан Microsoft около 2000 года как часть своего"
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ".СЕТЬ" ""(пустой строки) "инициатива"
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ""(пустой строки) "C #" ""(пустой строки)
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ".СЕТЬ" "C #" ""(пустой строки)
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» "АВС" "C #" ""(пустой строки)
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» ".СЕТЬ" «XYZ» ""(пустой строки)
«C # был разработан Microsoft около 2000 года в рамках инициативы .NET» "АВС" «XYZ» ""(пустой строки)

Правила

Это код-гольф . Побеждает ответ с наименьшим количеством байтов.

Ответы

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-мерному массиву

⌂debд далить е nding (передний и задний) б Ланкс

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 байт

Сохранено 9 байт благодаря movatica !!!
Сохранено 2 байта благодаря ovs !!!

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

Рубин , 66 байт

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

Попробуйте онлайн!

Другой метод без использования регулярного выражения,

Рубин , 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

Найдите ключевое слово start как можно раньше в строке плюс необязательные пробелы.

 *(.*?) *

Найдите как можно более короткий результат (чтобы ключевое слово end находилось в строке как можно раньше), но также обрезайте пробелы вокруг него.

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

Убедитесь, что ключевое слово end еще не было передано.

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

Если ключевое слово конца было пустым, то совпадение было только с концом строки, в противном случае совпадало ключевое слово конца и остальная часть строки.

|(.|¶)+

Если ничего сопоставить не удалось, удалите все.

$3

Сохраняйте желаемый результат.

1 att Jan 07 2021 at 13:42

Язык Wolfram Language (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

С (ССЗ) , 168 152 143 132 112 байт

Огромное количество -38 благодаря @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;}

Попробуйте онлайн!

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строка обрезается до пустой, если ее ввод отрицательный.)

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

Если ключевое слово start не пусто, разделите строку на ключевое слово, отбросьте первый элемент и снова присоедините строку. Это приводит к пустой строке, если ключевое слово start не появляется в строке.

≔⌕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 = True, чтобы текстовая строка не интерпретировалась как регулярное выражение), устанавливает связь substrмежду ними, а затем trimвыполняет wбыстрый переход sс обоих концов.

Поскольку каждая из функций ncharи regexprиспользуется дважды, определение односимвольных псевдонимов короче. В случае nchar, мы можем даже переопределить унарный оператор ?как его псевдоним, чтобы избежать необходимости в скобках. К сожалению, здесь этот трюк невозможен regexprиз-за необходимости fпередавать ему дополнительный аргумент ixed = 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():"";}