Obj-C: Create Array From String Where items are in <> - objective-c

I am trying to parse a String to an Array each item is between <> for example <this is column 1><this is column 2> etc....
Help would be much appreciated.
Thanks

Something to demonstrate:
NSString *string = #"<this is column 1><this is column 2>";
NSScanner *scanner = [NSScanner scannerWithString:string];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
NSString *temp;
while ([scanner isAtEnd] == NO)
{
// Disregard the result of the scanner because it returns NO if the
// "up to" string is the first one it encounters.
// You should still have this in case there are other characters
// between the right and left angle brackets.
(void) [scanner scanUpToString:#"<" intoString:NULL];
// Scan the left angle bracket to move the scanner location past it.
(void) [scanner scanString:#"<" intoString:NULL];
// Attempt to get the string.
BOOL success = [scanner scanUpToString:#">" intoString:&temp];
// Scan the right angle bracket to move the scanner location past it.
(void) [scanner scanString:#">" intoString:NULL];
if (success == YES)
{
[array addObject:temp];
}
}
NSLog(#"%#", array);

NSString *input =#"<one><two><three>";
NSString *strippedInput = [input stringByReplacingOccurencesOfString: #">" withString: #""]; //strips all > from input string
NSArray *array = [strippedInput componentsSeperatedByString:#"<"];
Note that [array objectAtIndex:0] will be an empty string ("") an this doesn't work of course, if one of the "actual" string contain < or >

One approach might be to use either componentsSeparatedByCharactersInSet or componentsSeparatedByString from NSString.
NSString *test = #"<one> <two> <three>";
NSArray *array1 = [test componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
NSArray *array2 = [test componentsSeparatedByString:#"<"];
You'll need to do some cleaning up afterward, either trimming in the case of array2 or removing white-space strings in the case of array1

Related

Add 1 to a number in an NSString that contains characters Objective-C

I am new to learning Objective-C (my first programming language!) and trying to write a little program that will add 1 to a number contained within a string. E.g. AA1BB becomes AA2BB.
.
So far I have tried to extract the number and add 1. Then extract the letters and add everything back together in a new string. I have had some success but can't manage to get back to the original arrangement of the initial string.
The code I have so far gives a result of 2BB and disregards the characters before the number which is not what I am after (the result I am trying for with this example would be AA2BB). I can't figure out why!
NSString* aString = #"AA1BB";
NSCharacterSet *numberCharset = [NSCharacterSet characterSetWithCharactersInString:#"0123456789-"]; //Creating a set of Characters object//
NSScanner *theScanner = [NSScanner scannerWithString:aString];
int someNumbers = 0;
while (![theScanner isAtEnd]) {
// Remove Letters
[theScanner scanUpToCharactersFromSet:numberCharset
intoString:NULL];
if ([theScanner scanInt:&someNumbers]) {}
}
NSCharacterSet *letterCharset = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
NSScanner *letterScanner = [NSScanner scannerWithString:aString];
NSString* someLetters;
while (![letterScanner isAtEnd]) {
// Remove numbers
[letterScanner scanUpToCharactersFromSet:letterCharset
intoString:NULL];
if ([letterScanner scanCharactersFromSet:letterCharset intoString:&someLetters]) {}
}
++someNumbers; //adds +1 to the Number//
NSString *newString = [[NSString alloc]initWithFormat:#"%i%#", someNumbers, someLetters];
NSLog (#"String is now %#", newString);
This is an alternative solution with Regular Expression.
It finds the range of the integer (\\d+ is one or more digits), extracts it, increments it and replaces the value at the given range.
NSString* aString = #"AA1BB";
NSRange range = [aString rangeOfString:#"\\d+" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSInteger numericValue = [aString substringWithRange:range].integerValue;
numericValue++;
aString = [aString stringByReplacingCharactersInRange:range withString:[NSString stringWithFormat:#"%ld", numericValue]];
}
NSLog(#"%#", aString);

How to parse a string format like [***]***?

I need to parse a string like [abc]000, and what I want to get is an array containing abc and 000. Is there an easy way to do it?
I'm using code like this:
NSString *sampleString = #"[abc]000";
NSArray *sampleParts = [sampleString componentsSeparatedByString:#"]"];
NSString *firstPart = [[[sampleParts objectAtIndex:0] componentsSeparatedByString:#"["] lastObject];
NSString *lastPart = [sampleParts lastObject];
But it's inefficient and didn't check whether the string is in a format like [**]**.
For this simple pattern, can just parse yourself like:
NSString *s = #"[abc]000";
NSString *firstPart = nil;
NSString *lastPart = nil;
if ([s characterAtIndex: 0] == '[') {
NSUInteger i = [s rangeOfString:#"]"].location;
if (i != NSNotFound) {
firstPart = [s substringWithRange:NSMakeRange(1, i - 1)];
lastPart = [s substringFromIndex:i + 1];
}
}
Or you could learn to use the NSScanner class.
As always, there are lots of ways to do this.
OPTION 1
If these are fixed length strings (each part is always three characters) then you can simply get the substrings directly:
NSString *sampleString = #"[abc]000";
NSString *left = [sampleString substringWithRange:NSMakeRange(1, 3)];
NSString *right = [sampleString substringWithRange:NSMakeRange(5, 3)];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
OPTION 1 (shortened)
NSArray *parts = #[ [sampleString substringWithRange:NSMakeRange(1, 3)],
[sampleString substringWithRange:NSMakeRange(5, 3)] ];
NSLog(#"%#", parts);
OPTION 2
If they aren't always three characters, then you can use NSScanner:
NSString *sampleString = #"[abc]000";
NSScanner *scanner = [NSScanner scannerWithString:sampleString];
// Skip the first character if we know that it will always start with the '['.
// If we can not make this assumption, then we would scan for the bracket instead.
scanner.scanLocation = 1;
NSString *left, *right;
// Save the characters until the right bracket into a string which we store in left.
[scanner scanUpToString:#"]" intoString:&left];
// Skip the right bracket
scanner.scanLocation++;
// Scan to the end (You can use any string for the scanUpToString that doesn't actually exist...
[scanner scanUpToString:#"\0" intoString:&right];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
RESULTS (for all options)
2013-05-10 00:25:02.031 Testing App[41906:11f03] (
abc,
000
)
NOTE
All of these assume well-formed strings, so you should include your own error checking.
try like this ,
NSString *sampleString = #"[abc]000";
NSString *pNRegex = #"\\[[a-z]{3}\\][0-9]{3}";
NSPredicate *PNTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pNRegex];
BOOL check=[PNTest evaluateWithObject:sampleString ];
NSLog(#"success:%i",check);
if success comes as 1 then you can perform the action for separating string into array.

Objective C: Get Substring between Double Quotes

What would be the best way to get every substring between double quotes and make it into an array?
For example, if the string (NSString) is:
#"abcd \"efgh\" ijklm \"no\" p \"qrst\" uvwx \"y\" z"
I want the result to be:
{#"efgh", #"no", #"qrst", #"y"}
as an NSArray.
This should get you started:
NSString *str = #"abcd \"efgh\" ijklm \"no\" p \"qrst\" uvwx \"y\" z";
NSMutableArray *target = [NSMutableArray array];
NSScanner *scanner = [NSScanner scannerWithString:str];
NSString *tmp;
while ([scanner isAtEnd] == NO)
{
[scanner scanUpToString:#"\"" intoString:NULL];
[scanner scanString:#"\"" intoString:NULL];
[scanner scanUpToString:#"\"" intoString:&tmp];
if ([scanner isAtEnd] == NO)
[target addObject:tmp];
[scanner scanString:#"\"" intoString:NULL];
}
for (NSString *item in target)
{
NSLog(#"%#", item);
}
One way would be to use componentsSeparatedByString: to split them based on ". This should give you an array of words the count of which should be odd. Filter all the even numbered words into an array. This should be your desired array.
Alternatively look at NSPredicate.

Objective-C: How to extract part of a String (e.g. start with '#')

I have a string as shown below,
NSString * aString = #"This is the #substring1 and #subString2 I want";
How can I select only the text starting with '#' (and ends with a space), in this case 'subString1' and 'subString2'?
Note: Question was edited for clarity
You can do this using an NSScanner to split the string up. This code will loop through a string and fill an array with substrings.
NSString * aString = #"This is the #substring1 and #subString2 I want";
NSMutableArray *substrings = [NSMutableArray new];
NSScanner *scanner = [NSScanner scannerWithString:aString];
[scanner scanUpToString:#"#" intoString:nil]; // Scan all characters before #
while(![scanner isAtEnd]) {
NSString *substring = nil;
[scanner scanString:#"#" intoString:nil]; // Scan the # character
if([scanner scanUpToString:#" " intoString:&substring]) {
// If the space immediately followed the #, this will be skipped
[substrings addObject:substring];
}
[scanner scanUpToString:#"#" intoString:nil]; // Scan all characters before next #
}
// do something with substrings
[substrings release];
Here is how the code works:
Scan up to a #. If it isn't found, the scanner will be at the end of the string.
If the scanner is at the end of the string, we are done.
Scan the # character so that it isn't in the output.
Scan up to a space, with the characters that are scanned stored in substring. If either the # was the last character, or was immediately followed by a space, the method will return NO. Otherwise it will return YES.
If characters were scanned (the method returned YES), add substring to the substrings array.
GOTO 1
[aString substringWithRange:NSMakeRange(13, 10)]
would give you substring1
You can calculate the range using:
NSRange startRange = [aString rangeOfString:#"#"];
NSRange endRange = [original rangeOfString:#"1"];
NSRange searchRange = NSMakeRange(startRange.location , endRange.location);
[aString substringWithRange:searchRange]
would give you substring1
Read more:
Position of a character in a NSString or NSMutableString
and
http://iosdevelopertips.com/cocoa/nsrange-and-nsstring-objects.html
Pretty simple, easy to understand version avoiding NSRange stuff:
NSArray * words = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSMutableArray * mutableWords = [NSMutableArray new];
for (NSString * word in words){
if ([word length] > 1 && [word characterAtIndex:0] == '#'){
NSString * editedWord = [word substringFromIndex:1];
[mutableWords addObject:editedWord];
}
}
Assuming that you are looking to find the first string that starts with a pound, and ends with a space, this might work. I don't have XCode in front of me, so forgive me if there's a syntax error or length off by 1 somewhere:
-(NSString *)StartsWithPound:(NSString *)str {
NSRange range = [str rangeOfString:#"#"];
if(range.length) {
NSRange rangeend = [str rangeOfString:#" " options:NSLiteralSearch range:NSMakeRange(range.location,[str length] - range.location - 1)];
if(rangeend.length) {
return [str substringWithRange:NSMakeRange(range.location,rangeend.location - range.location)];
}
else
{
return [str substringFromIndex:range.location];
}
}
else {
return #"";
}
}
Another simple solution:
NSRange hashtag = [aString rangeOfString:#"#"];
NSRange word = [[aString substringFromIndex:hashtag.location] rangeOfString:#" "];
NSString *hashtagWord = [aString substringWithRange:NSMakeRange(hashtag.location, word.location)];
This is what I'd do:
NSString *givenStringWithWhatYouNeed = #"What you want to look through";
NSArray *listOfWords = [givenStringWithWhatYouNeed componentsSeparatedByString:#" "];
for (NSString *word in listOfWords) {
if ([[word substringWithRange:NSMakeRange(0, 1)]isEqualToString:#"#"]) {
NSString *whatYouWant = [[word componentsSeparatedByString:#"#"]lastObject];
}
}
Then you can do what you need with the whatYouWant instances. If you want to know which string it is (if it's the substring 1 or 2), check the index of of word string in the listOfWords array.
I hope this helps.
A general and simple code to select all the words starting with "#" in a NSString is:
NSString * aString = #"This is the #substring1 and #subString2 ...";
NSMutableArray *selection=#[].mutableCopy;
while ([aString rangeOfString:#"#"].location != NSNotFound)
{
aString = [aString substringFromIndex:[aString rangeOfString:#"#"].location +1];
NSString *item=([aString rangeOfString:#" "].location != NSNotFound)?[aString substringToIndex:[aString rangeOfString:#" "].location]:aString;
[selection addObject:item];
}
if you still need the original string you can do a copy.
The inline conditional is used in case your selected item is the last word

How to use NSScanner?

I've just read Apple documentation for NSScanner.
I'm trying to get the integer of this string:
#"user logged (3 attempts)"
I can't find any example, how to scan within parentheses. Any ideas?
Here's the code:
NSString *logString = #"user logged (3 attempts)";
NSScanner *aScanner = [NSScanner scannerWithString:logString];
[aScanner scanInteger:anInteger];
NSLog(#"Attempts: %i", anInteger);
Ziltoid's solution works, but it's more code than you need.
I wouldn't bother instantiating an NSScanner for the given situation. NSCharacterSet and NSString give you all you need:
NSString *logString = #"user logged (3 attempts)";
NSString *digits = [logString stringByTrimmingCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
NSLog(#"Attempts: %i", [digits intValue]);
or in Swift:
let logString = "user logged (3 attempts)"
let nonDigits = NSCharacterSet.decimalDigitCharacterSet().invertedSet
let digits : NSString = logString.stringByTrimmingCharactersInSet(nonDigits)
NSLog("Attempts: %i", digits.intValue)
`Here is what I do to get certain values out of a string
First I have this method defined
- (NSString *)getDataBetweenFromString:(NSString *)data leftString:(NSString *)leftData rightString:(NSString *)rightData leftOffset:(NSInteger)leftPos;
{
NSInteger left, right;
NSString *foundData;
NSScanner *scanner=[NSScanner scannerWithString:data];
[scanner scanUpToString:leftData intoString: nil];
left = [scanner scanLocation];
[scanner setScanLocation:left + leftPos];
[scanner scanUpToString:rightData intoString: nil];
right = [scanner scanLocation] + 1;
left += leftPos;
foundData = [data substringWithRange: NSMakeRange(left, (right - left) - 1)]; return foundData;
}
Then call it.
foundData = [self getDataBetweenFromString:data leftString:#"user logged (" rightString:#"attempts)" leftOffset:13];
leftOffset is the number of characters for the left string
Could be an easier cleaner way but that was my solution.
Here is a simple solution using NSScanner (yes, #NSResponder has a really neat solution!):
NSString *logString = #"user logged (3 attempts)";
NSString *numberString;
NSScanner *scanner = [NSScanner scannerWithString:logString];
[scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
[scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&numberString];
NSLog(#"Attempts: %i", [numberString intValue]);
NSLog output:
Attempts: 3
NSScanner is a linear scanner. You have to scan through the stuff you don't want to get to what you do want.
You could do [aScanner scanUpToCharactersInSet:[NSCharacterSet decimalDigitCharacterSet] intoString:NULL] to jump past everything up to the number character. Then you do [aScanner scanInteger:&anInteger] to scan the character into an integer.
here is the reg-ex usage
NSString *logString = #"user logged (3 attempts)";
NSString * digits = [logString stringByMatching:#"([+\\-]?[0-9]+)" capture:1];