Modifying Occurrences of Time Format Regex in a Long String - ios

I have strings containing Time values like 08:30:00AM and/or 12:45:00PM etc.
Now what i need is to remove the part containing 'seconds' value in these strings to make upper strings like 08:30AM and/or 12:45PM etc.
I can't use NSDateFormatter as it's not necessary that the string always contain time string in HH:MM:SS value.. There could be any string value else.. That's why I have to do it through patttern matching.
I know, i can use the following code. But what I need to know is what will be the regex to find and modify the string.
NSString *string = #"string containing 08:30:00AM values and some text";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"???" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#""];
NSLog(#"%#", modifiedString);
Thanks in advance..

If it is time, then you can use dateformatter:
NSString *string = #"08:30:00AM"; //This is your input time
NSDateFormatter *df=[NSDateFormatter new];
[df setDateFormat:#"hh:mm:ssa"];
NSDate *nowTime=[df dateFromString:string];
[df setDateFormat:#"hh:mma"];
NSString *outputTime=[df stringFromDate:nowTime];
NSLog(#"time is : %#",outputTime);
Output: 08:30AM
EDIT:
Alternate way:
If you are sure your time is always in given format as 08:30:00AM and 08:30:05AM then you can use:
NSString *string = #"08:30:00AM";
NSString *aMPM=[string substringFromIndex:string.length-2];
NSString *noSecondAMPM= [string substringToIndex:string.length-5];
NSString *myTime=[NSString stringWithFormat: #"%#%#",noSecondAMPM,aMPM];
NSLog(#"time is : %#",myTime);

Just to give an answer along the lines of your own question, this regex pattern will match the time formats you are after and the parenthesis will capture the hour and minute part and allow you to keep them in the modified string:
NSString *timeText = #"This is a text with 08:30:23 and 9:23:54AM to test both formats.";
NSString *timePattern = #"([0-9]{1,2}:[0-9]{2}):[0-9]{2}";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:timePattern
options:0
error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:timeText
options:0
range:NSMakeRange(0, timeText.length)
withTemplate:#"$1"];
The result is this:
This is a text with 08:30 and 9:23AM to test both formats.
The $n (where n is a digit) in the replacement string refers to the nth capture group (parenthesis) in the regex pattern - in this case the hours, the colon and the minutes.
As you mentioned yourself, using regexes you can do the substitution directly in the text with no further parsing needed.
BTW, there are no letters in this pattern, so you don't need NSRegularExpressionCaseInsensitive.
This site is useful, e.g. the discussion on replacement strings and advanced syntax.

Related

Delete occurances at the end of a string - iOS

Say you have a NSString *testString = #"Abcd!!!!";, note the four exclamation marks, how can I delete all exclamation marks as efficiently as possible?
The exclamation marks can be any number of amount, and can only be deleted if they're in consecutive trailing order.
One example might be:
NSString *testString = #"ABC!D!!!!!";
The result would then be:
NSString *result = #"ABC!D";
Since you don't know how many ! you'll be removing from the string, you could do it with a regular expression.
NSString *string = #"ABC!D!!!!!";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"!+$" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#""];
NSLog(#"%#", modifiedString);
Regex aren't always the most efficient way to solve these sorts of problems, but in this case, I don't think there would be a measurable gain doing it another way.

Whats the quickest way to do lots of NSRange calls in a very long NSString on iOS?

I have a VERY long NSString. It contains about 100 strings I need to pull out of it, all randomly scattered throughout. They are all commonly are between imgurl= and &.
I could use NSRange and just loop through pulling out each string, but I'm wondering if there is a quicker was to pick out everything in a simple API call? Maybe something I am missing here?
Looking for the quickest way to do this. Thanks!
Using NSString methods componentsSeparatedByString and componentsSeparatedByCharactersInSet:
NSString *longString = some really long string;
NSArray *longStringComponents = [longString componentsSeparatedByString:#"imgurl="];
for (NSString *string in longStringComponents){
NSString *imgURLString = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"&"]] firstObject];
// do something with imgURLString...
}
If you feel adventurous then you can use regular expression. Since you said that the string you are looking is between imgurl and &, I assumed its a url and made the sample code to do the same.
NSString *str = #"http://www.example.com/image?imgurl=my_image_url1&imgurl=myimageurl2&somerandom=blah&imgurl=myurl3&someother=lol";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(?:imageurl=)(.*?)(?:&|\\r)"
options:NSRegularExpressionCaseInsensitive
error:&error];
//should do error checking here...
NSArray *matches = [regex matchesInString:str
options:0
range:NSMakeRange(0, [str length])];
for (NSTextCheckingResult *match in matches)
{
//[match rangeAtIndex:0] <- gives u the whole string matched.
//[match rangeAtIndex:1] <- gives u the first group you really care about.
NSLog(#"%#", [str substringWithRange:[match rangeAtIndex:1]]);
}
If I were you, I will still go with #bobnoble method because its easier and simpler compared to regex. You will have to do more error checking using this method.

stringByReplacingOccurrencesOfString function

I am new to ios development.
NSString *newString2 = [aString stringByReplacingOccurrencesOfString:#"1," withString:#""];
My problem is i do not know how to check for any number i.e. stringByReplacingOccurrencesOfString:#"anyInt," where any Int is any integer number from 1 to N.
Thanks in advance!
Using regular expressions is the best solution:
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[1-9]" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#""];
Check official NSRegularExpression documentation, there is also a good tutorial here
A regular expression is probably the easiest solution. Whether you want to remove just single digits or multiple digits, a regular expression can help.
NSString *aString = #"Apple 10, Banana 3, Carrot 5, Durian 42, Eggplant 4,";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[0-9]+," options:0 error:NULL];
NSString *newString = [regex stringByReplacingMatchesInString:aString options:0 range:NSMakeRange(0, [aString length]) withTemplate:#""];
NSLog(#"%#", newString);
// result should be "Apple Banana Carrot Durian Eggplant "
Regular expressions may seem overwhelming or difficult to understand at first, but it is only because they can be very powerful for searching and replacing text. Have a look at the overview section of the NSRegularExpression documentation for more information.
For nos in first part greater than 0, second part is shown. For 0 in first part, -- is shown.
Try the below code,
NSString * aString = #"1,10";
NSString *newString2;
NSArray *items = [aString componentsSeparatedByString:#","];
if([[items objectAtIndex:0] integerValue]>0)
newString2 = [items objectAtIndex:1];
else
newString2 = #"--";
Just these two lines to remove all numbers from a string.
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
NSString *newString = [[tempstr componentsSeparatedByCharactersInSet: numbers] componentsJoinedByString:#""];
If you want to check the range and then you want to replace then use below api:-
- (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement
why you want to check the existence of the Integer because ultimate you'll replace it with ''. So just use the below line
NSString *newString2 = [aString stringByReplacingOccurrencesOfString:[NSString StringWithFormat:#"%d", anyInt], withString:#""];
Above line will fulfill your requirement.

How properly extract substrings from an NSString without hardcoding positions?

I have this string returning:
"Monday thru Friday 8:00 AM - 7:30 PM"
I need to eliminate the mon-fri stuff in order to get this:
"8:00AM - 7:30PM"
And then I need to split it into opening time and closing time in order to determine if its open or not:
"8:00AM" && "7:30PM"
But there are a lot of stores and they have different opening and closing times, so I cant just extract 6 characters from 8 or anything like that.
So far I decided to go this route:
NSRange startRange = [storeTime.text rangeOfString:#"-"];
NSString *openString = [storeTime.text substringWithRange:NSMakeRange(16, startRange.location-17)];
NSString *closeString = [storeTime.text substringWithRange:NSMakeRange(startRange.location+2, storeTime.text.length-(startRange.location+2))];
But it just seems like i could break because of the hardcoded start at 16 and it makes me wonder if it could break anywhere else. Any better ideas on how to achieve this?
You can use NSRegularExpression to grab the two time strings out of a string:
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"\\d{1,2}:\\d{2} (AM|PM)"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSString *str = #"Monday thru Friday 8:00 AM - 7:30 PM";
NSArray *m = [regex matchesInString:str
options:0
range:NSMakeRange(0, str.length)];
If you know the text before the time interval is always in the format <someday> thru <someday>, then you can find the index of the first numerical character (digit), and get a substring from that index.
Then, split the time strings on #" - " using the componentsSeparatedByString: method.
Example:
NSString *s = #"monday thru sunday, 0:00 - 23:59";
NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
int idx = [s rangeOfChatacterFromSet:digits].location;
NSString *timeStr = [s substringFromIndex:idx];
NSArray *timeStrings = [timeStr componentsSeparatedByString:#" - "];
How about first go by replacing occurrences of some strings.
So use the [string stringByReplacingOccurrencesOfString:#"Monday" withString: #""];
remove all the days and probably the "thru" string.
Then you're left with the hours. Don't forget to watch for space characters.
Hope this helps.

NSMutableString replaceOccurrencesOfString replacing whole words

Is there a way to use replaceOccurrencesOfString (from NSMutableString) to replace whole words?
For example, if I want to replace all occurrences of a fraction in a string, like "1/2", I'd like that to match only that specific fraction. So if I had "11/2", I would not want that to match my "1/2" rule.
I've been trying to look for answers to this already, but I am having no luck.
You could use word boundaries \b with Regex. This example matches the "1/2" at the start and the end of the example string, but neither of the middle options
// Create your expression
NSString *string = #"1/2 of the 11/2 objects were 1/2ed in (1/2)";
NSError *error = nil;
NSRegularExpression *regex =
[NSRegularExpression
regularExpressionWithPattern:#"\\b1/2\\b"
options:NSRegularExpressionCaseInsensitive
error:&error];
// Replace the matches
NSString *modifiedString =
[regex stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
withTemplate:#"HALF USED TO BE HERE"];

Resources