How to find occurrence of a format in NSString - iphone

I am reading a feed, and need to find the occurrence of a string format, for example, in "Feed for 03/02/2012". Now this date will always be of the format: %#/%#/%#. I need to find is this format occurs, and thus extract the date. The date and month can be any, so i don't have a specific date to search for. I searched in the docs, could not find it. Only option possible to me seems to take all 12 combinations of a month like "/12/", and find the occurrence of any of these.
Is there any better approach?

You can use regular expressions:
NSString *feed = #"Feed for 03/02/2012";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"([0-9]{1,2})/([0-9]{1,2})/([0-2][0-9]{3})"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex enumerateMatchesInString:feed options:0 range:NSMakeRange(0, [feed length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
NSString *month = [feed substringWithRange:[match rangeAtIndex:1]];
NSString *day = [feed substringWithRange:[match rangeAtIndex:2]];
NSString *year = [feed substringWithRange:[match rangeAtIndex:3]];
//...
}];

Related

how to write NSRegularExpression to xx:xx:xx?

i am trying to check if NSString is in specific format. dd:dd:dd. I was thinking of NSRegularExpression. Something like
/^(\d)\d:\d\d:\d\d)$/ ?
Have you tried something like:
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^\d{2}:\d{2}:\d{2}$"
options:0
error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
options:0
range:NSMakeRange(0, [string length])];
(I haven't tested it, because I cannot right now, but it should be working)
I suggest to use RegexKitLite
With this and assuming that in dd:dd:dd 'd' actually stands for a digit from 0-9 it should be fairly easy to implement what you need given the additional comment from Grijesh.
Here's an example copied from the RegexKitLite page:
// finds phone number in format nnn-nnn-nnnn
NSString *regEx = #"{3}-[0-9]{3}-[0-9]{4}";
NSString *match = [textView.text stringByMatching:regEx];
if ([match isEqual:#""] == NO) {
NSLog(#"Phone number is %#", match);
} else {
NSLog(#"Not found.");
}
UPDATE:
NSString *idRegex = #"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]";
NSPredicate *idTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", idRegex];
for (NSString * str in newArrAfterPars) {
if ([idTest evaluateWithObject:str]) {
}
}

parsing string starting with # and # in objective-C

So I am trying to parse a string that has the following format:
baz#marroon#red#blue #big#cat#dog
or, it can also be separated by spaces:
baz #marroon #red #blue #big #cat #dog
and here's how I am doing it now:
- (void) parseTagsInComment:(NSString *) comment
{
if ([comment length] > 0){
NSArray * stringArray = [comment componentsSeparatedByString:#" "];
for (NSString * word in stringArray){
}
}
}
I've got the components separated by space working, but what if it has no space.. how do I iterate through these words? I was thinking of using regex.. but I have no idea on how to write such regex in objective-C. Any idea, for a regex that would cover both of these cases?
Here's my first attempt:
NSError * error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(#|#)\\S+" options:NSRegularExpressionCaseInsensitive error:&error];
NSArray* wordArray = [regex matchesInString:comment
options:0 range:NSMakeRange(0, [comment length])];
for (NSString * word in wordArray){
}
Which doesn't work.. I think my regex is wrong.
Here is a way to do it using NSScanner that puts the separated strings and a string representation of their ranges into an array (this assumes that your original string started with a # -- if it doesn't and you need it to, then just prepend the hash to the string at the start).
NSMutableArray *array = [NSMutableArray array];
NSString *str = #"#baz#marroon#red#blue #big#cat#dog";
NSScanner *scanner = [NSScanner scannerWithString:str];
NSCharacterSet *searchSet = [NSCharacterSet characterSetWithCharactersInString:#"##"];
NSString *outputString;
while (![scanner isAtEnd]) {
[scanner scanUpToCharactersFromSet:searchSet intoString:nil];
[scanner scanCharactersFromSet:searchSet intoString:&outputString];
NSString *symbol = [outputString copy];
[scanner scanUpToCharactersFromSet:searchSet intoString:&outputString];
NSString *wholePiece = [[symbol stringByAppendingString:outputString]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *rangeString = NSStringFromRange([str rangeOfString:wholePiece]);
[array addObject:wholePiece];
[array addObject:rangeString];
}
NSLog(#"%#",array);
I think the regular expression you really want is [##]?\\w+. It will find groups of letters optionally preceded by an # or #. Your expression wouldn't work because it looks for any non-space character, which includes # and #. (Depending on what can be in the "words," you might want something more or less specific than \w, but it isn't clear from the question.)
If you need the ranges, then NSRegularExpression probably works well:
NSString *comment = #"#baz#marroon#red#blue #big#cat#dog";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[##]\\w+" options:0 error:nil];
NSArray* wordArray = [regex matchesInString:comment
options:0
range:NSMakeRange(0, [comment length])];
for (NSTextCheckingResult *result in wordArray)
NSLog(#"%#", [comment substringWithRange:result.range]);
Or, [##][a-zA-z]+ works if you're ok with ASCII alpha words only.

Take part of string in-between symbols?

I would like to be able to take the numbers lying behind the ` symbol and in front of any character that is non-numerical and convert it into a integer.
Ex.
Original String: 2*3*(123`)
Result: 123
Original String: 4`12
Result: 4
Thanks,
Regards.
You can use regular expressions. You can find all the occurrences like this:
NSString *mystring = #"123(12`)456+1093`";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"([0-9]+)`" options:0 error:nil];
NSArray *matches = [regex matchesInString:mystring options:0 range:NSMakeRange(0, mystring.length)];
for (NSTextCheckingResult *match in matches) {
NSLog(#"%#", [mystring substringWithRange:[match rangeAtIndex:1]]);
}
// 12 and 1093
If you only need one occurrence, then replace the for loop with the following:
if (matches.count>0) {
NSTextCheckingResult *match = [matches objectAtIndex:0];
NSLog(#"%#", [mystring substringWithRange:[match rangeAtIndex:1]]);
}
There can be better way to do this, Quickly i could come up with this,
NSString *mystring = #"123(12`)";
NSString *neededString = nil;
NSScanner *scanner =[NSScanner scannerWithString:mystring];
[scanner scanUpToString:#"`" intoString:&neededString];
neededString = [self reverseString:neededString];
NSLog(#"%#",[self reverseString:[NSString stringWithFormat:#"%d",[neededString intValue]]]);
To reverse a string you can see this

NSSortDescriptor sorting by alpha numeric

I'm trying to sort results from a CoreData "table" of "Tracks" in a similar manner to iTunes. The problem is, "ASC" sort uses the first characters to sort so I end up with:
(I Can't Get No) Satisfaction
A Hard Days Night
I'd like The Stones to show up in the results with "I", basically ignorning anything ^A-Za-z0-9. I've tried a custom selector and comparator block but it just ignores it so I'm stuck.
From my experience you're better off having a sortName attribute that you generate on object creation. You can then use that key to sort your CoreData results in a much simpler and faster fashion.
Another solution would be to sort manually after fetching the results:
[tracks sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSError *error = nil;
NSString *pattern = #"[^A-Za-z0-9]";
NSRegularExpression *expr = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:&error];
NSString *title1 = [(Track *)obj1 title];
NSString *title2 = [(Track *)obj2 title];
NSString *title1Match = [expr stringByReplacingMatchesInString:title1
options:0
range:NSMakeRange(0, [title1 length])
withTemplate:#""];
NSString *title2Match = [expr stringByReplacingMatchesInString:title2
options:0
range:NSMakeRange(0, [title2 length])
withTemplate:#""];
return [title1Match compare:title2Match options:NSCaseInsensitiveSearch];
}];
I tried [\W] as the pattern as well but seemed like there was a huge performance hit.

returning all index of a character in a NSString

IS there a method that would return all the index of the occurences of the letter 'a' in a NSString lets say? Tried looking at the documentation and there seems that there isn't any. So I might have to break the NSString to an NSArray of chars and iterate?
Try [NSRegularExpression enumerateMatchesInString:options:range:usingBlock:]. Or indeed, any of the other NSRegularExpression matching methods. They won't return an NSIndexSet - it'll be an array of NSTextChecking objects - but you can quite easily get the index out of that.
Here's some (untested!) sample code:
NSString* aString = #"Here's a string, that contains some letters a";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"a" options:0 error:NULL];
NSArray* matches = [regex matchesInString:aString options:0 range:NSMakeRange(0,[aString length])];
for(NSTextCheckingResult* i in matches) {
NSRange range = i.range;
NSUInteger index = range.location; //the index you were looking for!
//do something here
}
It's actually more efficient to use enumerateMatchesInString, but I don't know how familiar you are with Blocks, so I opted for the more common fast enumeration of an NSArray.
Update: the same code using Blocks.
NSString* aString = #"Here's a string, that contains some letters a";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"a";
[regex enumerateMatchesInString:aString
options:0
range:NSMakeRange(0,[aString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range = result.range;
NSUInteger index = range.location; //the index you were looking for
//do work here
}];
NSString *full_string=#"The Quick Brown Fox Brown";
NSMutableArray *countloc=[[NSMutableArray alloc]init];
int temp=0;
int len=[full_string length];
for(int i =0;i<[full_string length];i++)
{
NSRange range=[full_string rangeOfString:#"Brown" options:0 range:NSMakeRange(temp,len-1)];
if(range.location<[full_string length])
[countloc addObject:[NSString stringWithFormat:#"%d",range.location]];
temp=range.location+1;
len=[full_string length]-range.location;
i=temp;
}
Here searching for the substring Brown and
Location of the substring is stored in the array countloc