24 часа в 12 часов преобразования времени, вставьте символ в строку - PullRequest
0 голосов
/ 10 июля 2010

Это своего рода второстепенный вопрос к моему вопросу здесь , но было предложено разделить вопросы для лучшего ответа.

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

Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700  
Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600  
Mon-Thu 900-1600, Fri 900-1700  

И нужно, чтобы она читалась следующим образом, например:

Mon-Wed 9:30am-5:00pm;Thu 9:00am-5:00pm;Fri 9:30am-5:00pm;Sat 9:00am-12:00pm, Home Lending Sat 9:00am-4:00pm

Мне нужно вместо этого преобразовать время в 12час, что относительно легко с чем-токак

if (time > 1200) {  
    time = time - 1200
    //add the pm and the colon :
} else {
   //add the am and the colon :
}

Мой вопрос: как мне:
- сначала попытаться найти числа.
- вытащить их и преобразовать в int для выполнения вычислений (я думаю, с использованием intValue).
- выполнить вычисления и вставить их обратно в ту же позицию строки, включая am / pm и двоеточие.

Я попробовал использовать регулярные выражения из RegexKitLite, но как мне запомнить, где вставить его обратно в строку, а также как мне удалить то, что уже есть в строке, чтобы заменить его?например, 1700. Я предполагаю, что использую MutableStrings, но мне нужно немного помочь.

Вот код, над которым я работал, но не возражал бы, если бы было более простое решение, которое означало бы выбросить это ...1021 *

NSString *regexString = @"(\\s|-?)(\\d{3,4})(;?|\\s?|-?)";

NSRange matchedRange = NSMakeRange(NSNotFound,NSNotFound);

//loop while we haven't fixed all times in the string
while (!matchedRange.length == 0) {

    matchedRange = [openingHoursString rangeOfRegex:regexString capture: 2];

    if (!matchedRange.length == 0) {

        NSString *digits = [openingHoursStrinig substringWithRange: matchedRange];
        NSLog(@"digits string: %@", digits);

        //do calculations and add colon to digits string and reinsert to openingHoursString
    }
}

Ответы [ 2 ]

2 голосов
/ 11 июля 2010

Один из способов сделать это - поддержка блоков RegexKitLites:

NSString *string = @"Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700\nMon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600\nMon-Thu 900-1600, Fri 900-1700";

NSString *replaced = [string stringByReplacingOccurrencesOfRegex:@"(?<=[[:Pattern_Syntax:][:White_Space:]]|\\A)(\\d{1,2})(\\d{2,2})(?=[[:Pattern_Syntax:][:White_Space:]]|\\z)" usingBlock:^NSString *(NSInteger captureCount, NSString * const capturedStrings[captureCount], const NSRange capturedRanges[captureCount], volatile BOOL * const stop) {
  NSInteger hour = [capturedStrings[1] integerValue];
  NSString *amOrPMString = @"am";
  if(hour >= 12) { amOrPMString = @"pm"; if(hour > 12) { hour -= 12; } }

  return([NSString stringWithFormat:@"%d:%@%@", hour, capturedStrings[2], amOrPMString]);
}];

NSLog(@"Replaced:\n%@", replaced);

При запуске распечатывается следующее:

2010-07-10 17:42:10.650 RegexKitLite[26086:a0f] Replaced:
Mon-Wed 9:30am-5:00pm Thu 9:00am-5:00pm Fri 9:30am-5:00pm
Mon-Wed 9:30am-5:00pm Thu 9:00am-5:00pm Fri 9:30am-5:00pm Sat 9:00am-12:00pm, Home Lending Sat 9:00am-4:00pm
Mon-Thu 9:00am-4:00pm, Fri 9:00am-5:00pm

РЕДАКТИРОВАТЬ 2010/07/11 - Добавить информацию по запросу OP.

Объяснение регулярного выражения, использованного в примере, следующее (с разбивкой на четыре наиболее логичных блока)

1: (?<=[[:Pattern_Syntax:][:White_Space:]]|\A)
2: (\d{1,2})
3: (\d{2,2})
4: (?=[[:Pattern_Syntax:][:White_Space:]]|\z)

Часть 1

Последовательность (?<= ... ) означает «утверждение с предварительным просмотром», или в прозе, это примерно переводится во что-то вроде «Если следующая часть регулярного выражения (в данном случае, # 2),тогда текст перед # 2 должен соответствовать регулярному выражению, заключенному в эти круглые скобки ".

Регулярное выражение" заключенному в эти круглые скобки "в данном случае равно [[:Pattern_Syntax:][:White_Space:]]|\A.Это регулярное выражение в грубой прозе говорит: «Сопоставьте любой символ в наборе символов со свойством Unicode Pattern_Syntax или White_Space или \A, что означает Match at the beginning of the input. Differs from ^ in that \A will not match after a new-line within the input..Символы Pattern_Syntax или White_Space - это такие символы, как '' (пробел), '\ t' (табуляция), новые строки и т. Д. И т. Д. Pattern_Syntax такие символы, как '-', ',','% 'и т. д.

Части 2 и 3

Эти части довольно очевидны.\d соответствует «цифровому» символу, например «0» .. «9», а {x,y} означает «Совпадение не менее x, но не более y раз».

Часть 4

Часть 4, по сути, идентична части первой, за исключением того, что в ней используется «прогнозное утверждение» в форме (?=, и, как мы надеемся, значение должно быть очевидно из контекста объяснения вчасть 1. Другое отличие заключается в использовании \z, что означает «Сопоставить, если текущая позиция находится в конце ввода».

Зачем нужны \A и \z?В случае, если время является самым первым в строке или самым последним в строке, так как набор символов [] для сопоставления не содержит "или нет символа, если в начале или конце сопоставляемого текста».Например, пример строки OP заканчивается на ..., Fri 900-1700.Без |\z регулярное выражение не соответствовало бы последнему 1700.

Зачем нужны части 1 и 4?Их может не быть, в зависимости от точного формата текстовой строки для сопоставления.Поскольку я не могу много сказать о формате входной строки, я попытался сделать ее «достаточно надежной» и терпимой к широкому диапазону разумных входных данных.Определенно есть несколько способов сделать это.

Что делает Блок

Блок ^{} вызывается каждый раз, когда сопоставляется регулярное выражение.Детали о том, что было найдено, передаются в качестве аргументов в блоки.Затем блок возвращает новую строку, которая используется для замены всего текста, который был сопоставлен с регулярным выражением.Этот процесс повторяется до тех пор, пока в строке не останется совпадений с регулярным выражением.

Для ясности, исходная строка только "совпадает один раз".Например, данное регулярное выражение по существу соответствует любому «числу» в форме «NNN» или «NNNN».Для каждого совпадения вызывается блок, а затем поиск следующего совпадения в исходной строке начинается с самого следующего символа после последнего совпадения.Он не может «возвращаться» или «начинать заново».

Исходная строка не изменяется никоим образом.Вместо этого создается совершенно новая строка.Он создается по частям из «текста между совпадениями» и строк замены, возвращаемых Блоком.Когда все замены завершены, возвращается строка.

РЕДАКТИРОВАТЬ 2010/07/12 - добавить дополнительную информацию для каждого запроса OP (дополнительного).

Q Если бы я был более уверен в согласованности входного формата (такого как Day-DaySpaceTime ИЛИ DaySpaceTime), мог бы я просто получить какое-нибудь регулярное выражение, подобное этому?(\ S | -) (\ д {1,2}) (\ d {2,2}) (;? | \ s | -?). * +1066 *

A Если бы вы были более уверены в формате ввода, регулярное выражение определенно можно было бы изменить.Например, если вы были «абсолютно уверены», что ввод всегда будет иметь вид nNNN-nNNN (где нижний регистр n представляет «необязательную цифру», как в 900-1730 против 1100-1915)для «времен» код может быть изменен на что-то вроде:

NSString *string = @"Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700\nMon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600\nMon-Thu 900-1600, Fri 900-1700";

NSString *replaced = [string stringByReplacingOccurrencesOfRegex:@"\\b(\\d{1,2})(\\d{2,2})\\-(\\d{1,2})(\\d{2,2})\\b" usingBlock:^NSString *(NSInteger captureCount, NSString * const capturedStrings[captureCount], const NSRange capturedRanges[captureCount], volatile BOOL * const stop) {
  NSInteger firstHour = [capturedStrings[1] integerValue], secondHour = [capturedStrings[3] integerValue];
  NSString *firstAMorPMString = @"am", *secondAMorPMString = @"am";

  if(firstHour >= 12) { firstAMorPMString = @"pm"; if(firstHour > 12) { firstHour -= 12; } }
  if(secondHour >= 12) { secondAMorPMString = @"pm"; if(secondHour > 12) { secondHour -= 12; } }
  if(firstHour == 0) { firstHour = 12; }
  if(secondHour == 0) { secondHour = 12; }

  return([NSString stringWithFormat:@"%d:%@%@-%d:%@%@", firstHour, capturedStrings[2], firstAMorPMString, secondHour, capturedStrings[4], secondAMorPMString]);
}];

NSLog(@"Replaced:\n%@", replaced);

В этом примере оба «раза» обрабатываются как один фрагмент.\b, присутствующий в начале и в конце регулярного выражения, означает Match if the current position is a word boundary.Это предотвращает совпадение с чем-то вроде abc123-456def.Это более простая форма более сложных элементов [[:Pattern_Syntax:][:White_Space:]] в исходном примере, но это не обязательно означает одно и то же (хотя в большинстве случаев это довольно близко).

Еще одно преимуществосопоставляя оба раза как один фрагмент, это уменьшает количество потенциальных «ложных совпадений», которые могут произойти, если сопоставить их только один раз. Например, в первом примере «комментарий» из «Home econ 101» будет превращен в «Home»econ 1:01 ", что, вероятно, не то, что вам нужно. :)

Я также изменил пример так, чтобы" военное 24-часовое время "из" 000 "означало" 12:00 утра ", поэтомупредположение, что анализируемые значения времени всегда имеют 24-часовой формат военного времени.

Q Также (? <= ...) выглядит за синтаксической частью RegexKitLite или это стандартregex? </p>

A Это часть синтаксиса regex, принятого библиотекой ICU (именно это RegexKitLite использует для фактического сопоставления регулярных выражений). Стенд отсутствуетСинтаксис регулярного выражения ard "per se, хотя" большинство "обработчиков регулярных выражений принимает и (?<=...), и (?=...).

Q Извините, в вашем регулярном выражении у вас было четыре набораof () означает ли это, что есть capturedStrings [0], capturedStrings [1], capturedStrings [2], capturedStrings [3]?

A (?<=...) и (?=...) шаблоны - это то, что известно как «утверждения нулевой ширины».Они на самом деле не вносят вклад в текст, «захваченный» регулярным выражением, но должны соответствовать заданному тексту, чтобы общее регулярное выражение «соответствовало».Различие между словами «захваченный» и «совпадение» в предыдущем предложении состоит в том, что «захваченный» потребляет совпадающую часть ввода, тогда как «сопоставленный» - нет.Это позволяет вам создавать регулярные выражения, такие как (\d+)(?=,), что означает «Сопоставить и« захватить »одно или несколько чисел, за которыми должно следовать«, », но не захватывать запятую».Забегание вперед и оглядывание назад - определенно продвинутые, неопытные возможности регулярных выражений, которые трудно полностью объяснить в таком коротком посте, как этот.

Однако следует особо отметить, что ни (?<=...), ни(?=...) считается "захватом", в отличие от (\d{1,2})(\d{2,2}).Полное регулярное выражение из исходного примера содержит только два захвата, хотя всего в скобках четыре группы.

0 голосов
/ 10 июля 2010

Вот непроверенная идея:

NSString *regexString = @"\\d+|\\D+";
NSMutableString* result = [NSMutableString string];
for(NSString *match in [openingHoursString componentsMatchedByRegex:regexString])
{
    if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[match characterAtIndex:0]]) {
        int t = [match intValue];
        BOOL pm = t >= 1200;
        if (t >= 1300)
            t -= 1200;
        [result appendFormat:@"%d:%02d%s", t / 100, t % 100, pm ? "pm" : "am"];
    } else {
        [result appendString:match];
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...