Extract numbers from NSString - cocoa

How can I extract numbers from a string defined like:
NSString *getNumber = #"Price138.50 Code112.250"
I need to extract both 138.50 and 112.25 from this string.

Use NSScanner, slightly modified from this Apple example:
NSCharacterSet *numberCharset = [NSCharacterSet characterSetWithCharactersInString:#"0123456789-"];
NSScanner *theScanner = [NSScanner scannerWithString:aString];
while (![theScanner isAtEnd]) {
// Eat non-digits and negative sign
[theScanner scanUpToCharactersFromSet:numberCharset
intoString:NULL];
float aFloat;
if ([theScanner scanFloat:&aFloat]) {
NSLog(#"Found %f", aFloat);
}
}

NSString *getNumber = #"Price138.50 Code112.250";
getNumber = [getNumber stringByReplacingOccurrencesOfString:#"Price" withString:#""];
getNumber = [getNumber stringByReplacingOccurrencesOfString:#"Code" withString:#""];
getNumber = [getNumber stringByReplacingOccurrencesOfString:#" " withString:#","];
NSArray *values = [getNumber componentsSeparatedByString:#","];
NSLog(#"Price Value: %#", [values firstObject]);
NSLog(#"Code Value: %#", [values lastObject]);
If your string will be of same kind then this can be a possible way. Not Recommended.

Related

finding word after the match using NSString

I have varius log files to read. Each logs contain a report of a devices (printers).
What I can find is always the word 'firmware:' followed by the firmware revision like:
PTRE firmware: XER8673B2
The log does not seem to be very ordered, whereby the position of this text is not always on the same point or on the same line, but is always in the "PTRE firmawre: XXXXXXX" format.
How can I find XER8673B2 ? Any help is appreciated.
SOLVED (thanks to #roman-sausarnes), this is the code:
NSString *stringToSearch = [[NSString alloc] initWithContentsOfFile:#"path/to/log" encoding:NSUTF8StringEncoding error:nil];
NSString *preMatchString = #"PTRE firmware: ";
NSString *terminatingCharacter = #" ";
NSString *result = [[NSString alloc] init];
NSScanner *scanner = [NSScanner scannerWithString:stringToSearch];
[scanner scanUpToString:preMatchString intoString:NULL];
[scanner scanString:preMatchString intoString:NULL];
[scanner scanUpToString:terminatingCharacter intoString:&result];
NSLog(#"It's : %#", result);
The output is
It's : XER8673B2
Look at NSScanner. The code would look something like this:
NSString *stringToSearch = theStringThatYouWantToSearch;
NSString *preMatchString = #"firmware: ";
NSString *terminatingCharacter = " ";
NSString *result = [[NSString alloc] init];
NSScanner *scanner = [NSScanner scannerWithString:stringToSearch];
[scanner scanUpToString:preMatchString intoString:NULL];
[scanner scanString:preMatchString intoString:NULL];
[scanner scanUpToString:terminatingCharacter intoString:&result];
At the end, result should be the string that came after "firmware: " but before the next trailing space (" ").

Sort by Double Value and not String Value

I'm currently pulling info from an sql DB where the 'cachedDist' column is set as a double. However when I pull it into my app and create my array I turn it into an String and the sort will obviously be off, 18.15 will come before 2.15. How do I fix that in my code so it will sort distance as a Double and not a String?
In Bar object.
NSString *cachedDist
#property(nonatomic,copy) NSString *cachedDist;
#synthesize cachedDist;
My while loop in the View Controller.
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
Bar * bar = [[Bar alloc] init];
bar.barName = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
bar.barAddress = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
bar.barCity = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
bar.barState = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
bar.barZip = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
bar.barLat = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 8)];
bar.barLong = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 9)];
if (currentLoc == nil) {
NSLog(#"current location is nil %#", currentLoc);
}else{
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[bar.barLat doubleValue] longitude:[bar.barLong doubleValue]];
bar.cachedDist = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];
[thebars addObject:bar];
}
My sorting
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"cachedDist" ascending:YES];
sortedArray = [thebars sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
return sortedArray;
NSString has a method doubleValue to make this quite simple:
double cachedDistance = [cachedDistanceString doubleValue];
which you can use in a custom comparator for your sorting, or else make the property an NSNumber or double to make sorting that much easier. (I'm not sure how you are sorting...)
edit:
I re-evaluated your code, and now it looks like we are going from a double to a string to a double... we can cut out the middle-man, so to speak.
In your #prototype section, change the #property:
// #property(nonatomic,copy) NSString *cachedDist; // old way
#property(nonatomic) double cachedDist;
then assign it like this:
bar.cachedDistance = [currentLoc distanceFromLocation: barLocation]/1000;
and remove the lines which create a string from the distance (which is actually just a double).
Alternatively, if you want to be more object oriented, you can (should?) use NSNumber objects:
#property(nonatomic,copy) NSNumber *cachedDist;
...
bar.cachedDistance = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];

sorting NSArray of NSStrings by match occurrence

How can I sort NSArray by search pattern matching?
So if for example I have a search pattern equal 'xd' and an array of values:
axd
bxd
xdd
gtxd
xdc
how can I get the output like below:
xdc
xdd
axd
bxd
gtxd
Thank you in advance.
Use NSArray's sortedArrayUsingFunction: with a function that orders first by the position of the search term, then by the strings' natural ordering.
NSInteger sorter(id arg1, id arg2, void *context)
{
NSString *searchTerm = (NSString *)context;
NSRange range1 = [arg1 rangeOfString:searchTerm];
NSRange range2 = [arg2 rangeOfString:searchTerm];
if (range1.location < range2.location)
return NSOrderedAscending;
if (range1.location > range2.location)
return NSOrderedDescending;
return [arg1 compare:arg2];
}
NSArray *array = [NSArray arrayWithObjects:#"axd", #"bxd", #"xdd", #"gtxd", #"xdc", nil];
NSArray *sortedArray = [array sortedArrayUsingFunction:sorter context:#"xd"];
This prints:
2011-02-15 01:33:49.642 GreatApp[78849:a0f] (
xdc,
xdd,
axd,
bxd,
gtxd
)
You can use NSArray's sortedArrayUsingFunction:context: method:
NSInteger occurenceSort(NSString* s1, NSString* s2, void *context)
{
NSRange range1 = [s1 rangeOfString:(NSString*)context];
NSRange range2 = [s2 rangeOfString:(NSString*)context];
if (range1.location < range2.location)
return NSOrderedAscending;
else if (range1.location > range2.location)
return NSOrderedDescending;
return NSOrderedSame;
}
...
NSString *stringToSearch = #"xd";
NSArray *sorterArray = [yourArray sortedArrayUsingFunction:occurenceSort context:stringToSearch];

Cocoa - Trim all leading whitespace from NSString

(have searched, but not been able to find a simple solution to this one either here, or in Cocoa docs)
Q. How can I trim all leading whitespace only from an NSString? (i.e. leaving any other whitespace intact.)
Unfortunately, for my purposes, NSString's stringByTrimmingCharactersInSet method works on both leading and trailing.
Mac OS X 10.4 compatibility needed, manual GC.
This creates an NSString category to do what you need. With this, you can call NSString *newString = [mystring stringByTrimmingLeadingWhitespace]; to get a copy minus leading whitespace. (Code is untested, may require some minor debugging.)
#interface NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace;
#end
#implementation NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace {
NSInteger i = 0;
while ((i < [self length])
&& [[NSCharacterSet whitespaceCharacterSet] characterIsMember:[self characterAtIndex:i]]) {
i++;
}
return [self substringFromIndex:i];
}
#end
This is another solution using Regular Expressions (requires iOS 3.2):
NSRange range = [string rangeOfString:#"^\\s*" options:NSRegularExpressionSearch];
NSString *result = [string stringByReplacingCharactersInRange:range withString:#""];
And if you want to trim the trailing whitespaces only you can use #"\\s*$" instead.
This code is taking blanks.
NSString *trimmedText = [strResult stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"%#",trimmedText);
Here is a very efficient (uses CoreFoundation) way of doing it (Taken from kissxml):
- (NSString *)trimWhitespace {
NSMutableString *mStr = [self mutableCopy];
CFStringTrimWhitespace((CFMutableStringRef)mStr);
NSString *result = [mStr copy];
[mStr release];
return [result autorelease];
}
NSString *myText = #" foo ";
NSString *trimmedText = [myText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSLog(#"old = [%#], trimmed = [%#]", myText, trimmedText);
Here's what I would do, and it doesn't involve categories!
NSString* outputString = inputString;
NSRange range = [inputString rangeOfCharacterFromSet: [NSCharacterSet whitespaceCharacterSet]
options:0];
if (range.location == 0)
outputString = [inputString substringFromIndex: range.location + range.length];
This is much less code.
I didn't really have much time to test this, and I'm not sure if 10.4 contains the UTF8String method for NSString, but here's how I'd do it:
NSString+Trimming.h
#import <Foundation/Foundation.h>
#interface NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront;
#end
NSString+Trimming.m
#import "NSString+Trimming.h"
#implementation NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront
{
const char *cStringValue = [self UTF8String];
int i;
for (i = 0; cStringValue[i] != '\0' && isspace(cStringValue[i]); i++);
return [self substringFromIndex:i];
}
#end
It may not be the most efficient way of doing this but it should work.
str = [str stringByReplacingOccurrencesOfString:#" " withString:#""];

cocoa: NSString not removing all the characters

I have an int and for some reason it isn't working after 16 or so. Here's my code:
NSArray *sortedArray;
sortedArray = [doesntContainAnother sortedArrayUsingFunction:firstNumSort context:NULL];
int count2 = [sortedArray count];
//NSLog(#"%d", count2);
int z = 0;
while (z < count2) {
NSString *myString = [sortedArray objectAtIndex:z];
NSString *intstring = [NSString stringWithFormat:#"%d", z];
NSString *stringWithoutSpaces;
stringWithoutSpaces = [[myString stringByReplacingOccurrencesOfString:intstring
withString:#""] mutableCopy];
[hopefulfinal addObject:stringWithoutSpaces];
NSLog(#"%#", [hopefulfinal objectAtIndex:z]);
z++;
}
Edit: It's not the int, it's the stringWithoutSpaces line... I can't figure out what's causing it.
So it (the NSLog, see above the z++) looks like this:
"Here"
"whatever"
"17 whatevere"
"18 this"
etc.
I'm guessing this is related to your earlier question Sort NSArray’s by an int contained in the array, and that you're trying to strip the leading number and whitespace from an array that looks like the one you had in that question:
"0 Here is an object"
"1 What the heck, here's another!"
"2 Let's put 2 here too!"
"3 Let's put this one right here"
"4 Here's another object"
Without know the full input, I'd guess that your code is likely failing because the leading numbers and the value of z are getting out of sync. Since you don't seem to actually care what the leading number is and just want to vamoose it, I'd recommend a different approach that scans for leading digits and extracts the substring from the position where those digits end:
NSArray *array = [NSArray arrayWithObjects:#"1 One",
#"2 Two",
#"5 Five",
#"17 Seventeen",
nil];
NSMutableArray *results = [NSMutableArray array];
NSScanner *scanner;
NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
for (NSString *item in array) {
scanner = [NSScanner scannerWithString:item];
[scanner scanInteger:NULL]; // throwing away the BOOL return value...
// if string does not start with a number,
// the scanLocation will be 0, which is good.
[results addObject:[[item substringFromIndex:[scanner scanLocation]]
stringByTrimmingCharactersInSet:whitespace]];
}
NSLog(#"Resulting array is: %#", results);
// Resulting array is: (
// One,
// Two,
// Five,
// Seventeen
// )
)

Resources