2015-12-11 2 views
7

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

Строка Пример перерыва привязанных к задаче может выглядеть следующим образом:

1:19 PM - 10:33 вечера ели тако 10:35 PM - 11:38 вечера 12:40 AM - 1:24 утра принял дремоту

Мне нужно сгруппировать это во временные марки со связанными описаниями. Выше, должны быть сгруппированы как:

1:19 вечера - 10:33 вечера ели тако

10:35 вечера - 11:38 вечера

12:40 AM - 1:24 утра поспал

Описание интервала прерывания может содержать в основном любые символы или быть любой длиной. В некоторых интервалах нет описаний.

Я считаю, что регулярное выражение будет самым простым способом получить массив интервалов с их описаниями (если они есть).

До сих пор у меня есть:

\d{1,2}:\d{2}[ap]m\s–\s\d{1,2}:\d{2}[ap]m 

, который соответствует метки времени 1:19pm – 10:33pm, 10:35pm – 11:38pm и 12:40am – 1:24am

Я использую JavaScript, а также функцию match, чтобы разобрать эти данные. Я хочу сделать регулярное выражение, которое будет соответствовать отметке времени и всему, что следует за ней, до следующей отметки времени.

Я новичок с регулярным выражением, поэтому легко на меня. Я был в этом часами, смотрел несколько видеороликов, читал учебники и экспериментировал с regex101. Якоря, взгляды/затылки, сбивают с толку, и я не могу заставить ничего делать, что хочу. Не желая стать экспертом в написании регулярных выражений, но мне бы очень хотелось узнать что-то новое, которое можно применить непосредственно к тому, что я делаю.

ответ

5

Вы можете использовать следующее регулярное выражение:

(\d{1,2}:\d{2}[ap]m\s*–\s*\d{1,2}:\d{2}[ap]m)(\D*(?:\d(?!\d?:\d{2}[ap]m\s)\D*)*) 

ВИДЕТЬ regex demo

Проблема, с которой вы сталкиваетесь, - , соответствующий тексту, который делает n ot соответствует определенному рисунку. Это может быть достигнуто либо с закаленным жадным токеном, либо методом unroll-the-loop. Последнее предпочтительнее, поскольку оно требует меньшего возврата. Мое регулярное выражение основано на этой технике.

Вот регулярное выражение Объяснение:

  • (\d{1,2}:\d{2}[ap]m\s*–\s*\d{1,2}:\d{2}[ap]m) - спички и захватывается Group # 1 период времени (я просто добавил внешние скобки и * кванторов \s классов) - как это ваше регулярное выражение, Я не буду вдаваться в детали
  • (\D*(?:\d(?!\d?:\d{2}[ap]m\s)\D*)*) - это развернутая конструкция .*?(?=\d{1,2}:\d{2}[ap]m\s), соответствующая любому шаблону до \d{1,2}:\d{2}[ap]m\s. Он помещается в группу №2.
    • \D* - 0 или более последовательности ...
      • \d(?!\d?:\d{2}[ap]m\s) - - 0 или больше, чем другие цифры
      • (?:\d(?!\d?:\d{2}[ap]m\s)\D*)* символов цифра (\d), не следует 1 или 0 цифр с последующими с : следует с 2 цифрами, затем a или p, затем m, а затем через пробел
      • \D* - снова, 0 или больше символов, кроме цифр.

JS демо:

var re = /(\d{1,2}:\d{2}[ap]m\s*–\s*\d{1,2}:\d{2}[ap]m)(\D*(?:\d(?!\d?:\d{2}[ap]m\s)\D*)*)/ig; 
 
var str = '1:19pm – 10:33pm ate tacos 10:35pm – 11:38pm 12:40am – 1:24am took a nap'; 
 
var m; 
 
    
 
while ((m = re.exec(str)) !== null) { 
 
    document.getElementById("r").innerHTML += "Period: " + m[1] + "<br/>"; 
 
    document.getElementById("r").innerHTML += "Description: " + m[2] + "<br/><br/>"; 
 
}
<div id="r"/>

+1

Я думал, что вы заинтересованы в организации вывода в какой-то более читаемой форме, поэтому я предложил две группы захвата. Обратите внимание, что в другом рабочем решении используется конструкция, которая может привести к катастрофическому обратному отскоку, если ваш вход большой. Регуляции Unroll-the-loop не подвержены этой проблеме. –

+0

Вы в этой теме, какой отличный ответ. – jgoodhcg

+1

Обратите внимание, что если шаблон регулярного выражения известен заранее, метод * * unroll-the-loop * (или * Unrolled Star Alternation Solution *)] (http://www.rexegg.com/regex-quantifiers.html#unrolled_staralt) является наиболее подходящим для соответствия самому близкому появлению подшаблона. Если вы используете переменную, вы должны использовать [* tempered greedy token *] (http://www.rexegg.com/regex-quantifiers.html#tempered_greed) или нережимное решение, если оно неэффективно достаточно. –

2

надеются, что это поможет:

https://regex101.com/r/dV7vY5/1

(\ д {1,2}: \ д {2} [ар] м) - (\ д {1,2}: \ д {2} [ар] м) ([\ S | AZ | AZ] +)

выход:

1:19 PM - 10:33 вечера ели тако

10:35 вечера - 11:38 вечера

12:40 утра - 1:24 утра поспал

и вы можете Асесс каждый скороговоркой:

$1 - first hour (1:19pm) 
$2 - second hour (10:33pm) 
$3 - string  (ate tacos) 

пример ниже:

var string = '1:19pm – 10:33pm ate tacos 10:35pm – 11:38pm 12:40am – 1:24am took a nap'; 
 
var regex = /(\d{1,2}:\d{2}[ap]m) – (\d{1,2}:\d{2}[ap]m)([\s|a-z|A-Z]+)/gi; 
 
var eachMatche = string.match(regex); 
 

 
for (var i = 0; i < eachMatche.length; i++) { 
 
    snippet.log(eachMatche[i]); 
 
    snippet.log('period : '+ eachMatche[i].replace(regex,'$1') +' - ' + eachMatche[i].replace(regex,'$2')); 
 
    snippet.log('description : '+eachMatche[i].replace(regex,'$3')); 
 
}
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

+2

Что делать, если описание содержит символы Unicode? Вы можете только совпадать с буквами ASCII, буквами '|' и пробелами теперь с '[\ s | a-z | A-Z]'. –

+0

хорошо пункт! Думаю, это просто улучшит ситуацию! если у вас есть ответ, обновите мой код. :) спасибо @stribizhev –

+0

Я предоставил свой собственный ответ. –

4

Я уверен, что это может быть упрощена, но следующее регулярное выражение, кажется, работает:

Example Here

/(\d{1,2}:\d{2}[ap]m\s–\s\d{1,2}:\d{2}[ap]m(?:.(?!\d{1,2}:\d{2}[ap]m))*)/g 

var input = '1:19pm – 10:33pm ate tacos 10:35pm – 11:38pm 12:40am – 1:24am took a nap'; 
 
var matches = input.match(/(\d{1,2}:\d{2}[ap]m\s–\s\d{1,2}:\d{2}[ap]m(?:.(?!\d{1,2}:\d{2}[ap]m))*)/g); 
 

 
for (var i = 0; i < matches.length; i++) { 
 
    snippet.log(matches[i]); 
 
}
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Выход:

13:19 - 22:33 ели тако

10:35 вечера - 11:38 вечера

12:40 AM - 1:24 утра поспал

+1

Вы используете конструкцию, похожую на темный алчный токен. Мое регулярное выражение на основе разворачивания техники цикла намного более эффективно, потому что оно не проверяет каждого персонажа и работает с многострочным контентом без каких-либо дополнительных настроек. Ваш '(?:. (?! \ D {1,2}: \ d {2} [ap] m)) *' захлестнет новую строку. –

+0

@stribizhev Я понял; ваш явно лучше. Я не специалист по регулярному выражению, как вы :) –

+0

Тем не менее, большинство людей думает, что регулярное выражение должно быть читаемым, а не эффективным, поэтому я часто «теряю» принятые знаки :) –

Смежные вопросы