split NSString using componentsSeparatedByString - objective-c

I have a string I need to split. It would be easy using componentsSeparatedByString but my problem is that the separator is a comma but I could have commas that aren't separator.
I explain:
My string:
NSString *str = #"black,red, blue,yellow";
the comma between red and blue must not be considered as separator.
I can determine if comma is a separator or not checking if after it there is a white space.
The goal is to obtain an array with:
(
black,
"red, blue",
yellow
)

This is tricky. First replace all occurences of ', ' (comma+space) with say '|' then use components separated method. Once you are done, again replace '|' with ', ' (comma+space).

Just to complete the picture, a solution that uses a regular expression to directly identify commas not followed by white space, as you explain in your question.
As others have suggested, use this pattern to substitute with a temporary separator string and split by that.
NSString *pattern = #",(?!\\s)"; // Match a comma not followed by white space.
NSString *tempSeparator = #"SomeTempSeparatorString"; // You can also just use "|", as long as you are sure it is not in your input.
// Now replace the single commas but not the ones you want to keep
NSString *cleanedStr = [str stringByReplacingOccurrencesOfString: pattern
withString: tempSeparator
options: NSRegularExpressionSearch
range: NSMakeRange(0, str.length)];
// Now all that is needed is to split the string
NSArray *result = [cleanedStr componentsSeparatedByString: tempSeparator];
If you are not familiar with the regex pattern used, the (?!\\s) is a negative lookahead, which you can find explained quite well, for instance here.

Here is coding implementation for cronyneaus4u's solution:
NSString *str = #"black,red, blue,yellow";
str = [str stringByReplacingOccurrencesOfString:#", " withString:#"|"];
NSArray *wordArray = [str componentsSeparatedByString:#","];
NSMutableArray *finalArray = [NSMutableArray array];
for (NSString *str in wordArray)
{
str = [str stringByReplacingOccurrencesOfString:#"|" withString:#", "];
[finalArray addObject:str];
}
NSLog(#"finalArray = %#", finalArray);

NSString *str = #"black,red, blue,yellow";
NSArray *array = [str componentsSeparatedByString:#","];
NSMutableArray *finalArray = [[NSMutableArray alloc] init];
for (int i=0; i < [array count]; i++) {
NSString *str1 = [array objectAtIndex:i];
if ([[str1 substringToIndex:1] isEqualToString:#" "]) {
NSString *str2 = [finalArray objectAtIndex:(i-1)];
str2 = [NSString stringWithFormat:#"%#,%#",str2,str1];
[finalArray replaceObjectAtIndex:(i-1) withObject:str2];
}
else {
[finalArray addObject:str1];
}
}
NSLog(#"final array count : %d description : %#",[finalArray count],[finalArray description]);
Output:
final array count : 3 description : (
black,
"red, blue",
yellow
)

Related

How to remove the first space from the NSString?

I want to remove only first space in below string.
NSString *str = #"IF_Distance (GET_Mi mi=km*1.4,STRING1,STRING2)";
Note: There is a space after IF_Distance and another space after
GET_Mi. I am unable to remove the space after IF_Distance.
Use rangeOfString: to locate the first space, then use stringByReplacingCharactersInRange:withString: to replace it with the empty string.
Remove space by using below code.
NSString *str = #"IF_Distance (GET_Mi mi=km*1.4,STRING1,STRING2)";
NSString *secondString = [str stringByReplacingOccurrencesOfString:#"IF_Distance " withString:#"IF_Distance"];
Try This:
NSString *str = #"IF_Distance (GET_Mi mi=km*1.4,STRING1,STRING2)";
NSString *firstStringContainingSpace = [[str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] firstObject];//firstStringContainingSpace = IF_Distance
str = [str stringByReplacingCharactersInRange:[str rangeOfString:[NSString stringWithFormat:#"%# ",firstStringContainingSpace]] withString:firstStringContainingSpace];
Output:
str = #"IF_Distance(GET_Mi mi=km*1.4,STRING1,STRING2)";
You can remove first space by using following code:
First find space by using rangeOfString: and then remove by using stringByReplacingCharactersInRange:withString: method.
Like,
NSString *str = #"IF_Distance (GET_Mi mi=km*1.4,STRING1,STRING2)";
NSString *strSpace = #" ";
NSRange range = [str rangeOfString:strSpace];
NSString *strFinal;
if (NSNotFound != range.location) {
strFinal = [str stringByReplacingCharactersInRange:range withString:#""];
}
If you are looking for some more universal way - this is the variant of it:
- (NSString *)removeWhitespaces:(NSString *)string {
NSMutableArray * stringComponents = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] mutableCopy];
NSString * fStringComponent = [stringComponents firstObject];
[stringComponents removeObject:fStringComponent];
return [fStringComponent stringByAppendingString:[stringComponents componentsJoinedByString:#" "]];
}

Objective C - Split NSString into Array, max count

I am new to Objective-C, so I am trying to split an String into an Array in this format:
NSString *str = #":49:DE:Bahnhofsstr:12:39:11";
NSArray *arr = [str componentsSeparatedByString:#":"];
I receive the following objects in arr:
[#"", #"49", #"DE", #"Bahnhofsstr", #"12", #"39", #"11"]
But I need it in this format:
[#"", #"49", #"DE", #"Bahnhofsstr:12:39:11"]
Anyone have any ideas?
You can use a regular expression. The one you want is this:
^([^:]*):([^:]*):([^:]*):(.*)$
The above matches three sequences of characters without colons in separated by colons and then a fourth group consisting of any kind of character. The ^ at the front and the $ at the end match the beginning and the end of the string respectively otherwise nonsense like 1:2:3:4:49:DE:Bahnhofsstr:12:39:11 would match because there is a match embedded in the string.
The parenthesis delimit capture groups which will be returned to you once the regular expression matching has been done. The first capture group is all the characters up to the first colon. The second capture group is all the characters between the first and second colons. The third capture group is all the characters between the second and third colons and the fourth capture group is all the characters after the third colon.
There is also a zeroth capture group which is the entire matching sequence.
Here's how to use this in Objective-C:
NSString* pattern = #"^([^:]*):([^:]*):([^:]*):(.*)$";
NSString* line = #":49:DE:Bahnhofsstr:12:39:11";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: pattern
options: 0
error: &error];
if (regex == nil)
{
NSLog(#"Invalid regular expression %#, %#", pattern, error);
}
else
{
NSArray* matches = [regex matchesInString: line
options: 0
range: NSMakeRange(0, [line length])];
if ([matches count] == 1)
{
// Should only be one match
NSTextCheckingResult* result = [matches objectAtIndex: 0];
NSMutableArray* captureGroups = [[NSMutableArray alloc] init];
// Omit capture group 0 because it will be the whole string
for (int i = 1 ; i < [result numberOfRanges] ; i++)
{
NSRange groupRange = [result rangeAtIndex: i];
NSString* captureGroup = [line substringWithRange: groupRange];
[captureGroups addObject: captureGroup];
}
NSLog(#"The fields are %#", captureGroups);
}
else
{
// match error
}
}
Regular expressions, as proposed by JeremyP, are an obvious solution to this sort of problem.
Some people don't like regexes, though, so another solution is to use NSScanner which is also made to scan strings and read the result into variables. Given that the delimiter is the same for all fields, it even lends itself to use a nice loop, reducing the tedious scanning code.
Here is an example:
NSString *str = #":49:DE:Bahnhofsstr:12:39:11";
const NSUInteger nFields = 4;
NSScanner *myScanner = [NSScanner scannerWithString: str];
NSMutableArray *arr = [NSMutableArray array];
for (NSUInteger i = 0; i < nFields - 1; i++) {
NSString *field;
// The BOOLs here really ought to be checked
BOOL found = [myScanner scanUpToString: #":" intoString: &field];
BOOL passedDelimiter = [myScanner scanString: #":" intoString: NULL];
[arr addObject: field ?: #"" ];
}
NSString *lastField = [[myScanner string] substringFromIndex:[myScanner scanLocation]];
[arr addObject: lastField];
That last line to read the remainder of the string is taken straight from the docs for NSScanner.

how to remove spaces, brackets and " from nsarray

I have an array where i am trying to remove the access spaces, brackets and " from the nsarray in order to use componentsSeparatedByString:#";"
NSArray *paths = [dic valueForKey:#"PATH"];
for(NSString *s in paths)
{
NSLog(#"String: %#", s);
}
String: (
"29858,39812;29856,39812;29800,39819;29668,39843;29650,39847;29613,39855;29613,39855;29613,39856;29605,39857;29603,39867;29603,39867;29599,39892;29596,39909;29587,39957;29571,40018;29563,40038;29560,40043"
)
this is the output give as show there are spaces, brackets and " how could i remove them
?
As this line is juz a string inside that array "29858,39812;29856,39812;29800,39819;29668,39843;29650,39847;29613,39855;29613,‌​39855;29613,39856;29605,39857;29603,39867;29603,39867;29599,39892;29596,39909;295‌​87,39957;29571,40018;29563,40038;29560,40043" this line is a string inside the path array and i try using componentsSeparatedByString:#";" it could not be spilt all there are spaces brackets and " inside.
Try stringByTrimmingCharactersInSet:
NSCharacterSet *charsToTrim = [NSCharacterSet characterSetWithCharactersInString:#"() \n\""];
s = [s stringByTrimmingCharactersInSet:charsToTrim];
try to use:
s = [s stringByReplacingOccurrencesOfString:#";"
withString:#""];
it separates the numbers for you and you can work with them as i.e. NSInteger values.
NSString *_inputString = #"29858,39812;29856,39812;29800,39819;29668,39843;29650,39847;29613,39855;29613,39855;29613,39856;29605,39857;29603,39867;29603,39867;29599,39892;29596,39909;29587,39957;29571,40018;29563,40038;29560,40043";
NSString *_setCommonSeparator = [_inputString stringByReplacingOccurrencesOfString:#";" withString:#","];
NSArray *_separetedNumbers = [_setCommonSeparator componentsSeparatedByString:#","];
for (NSString *_currentNumber in _separetedNumbers) {
NSInteger _integer = [_currentNumber integerValue];
NSLog(#"number : %d", _integer);
}

Cocoa xcode4.3 hide characters of a string

I am adding string into a pickerView like this :
NSString *string = [NSString stringWithFormat:#"%# %#", xxx, xxx];
[pickerViewObjects addObject:string];
what i want to do is to hide the first part of the string, or of there's something to use like charachterAtIndex it will be useful because the first part of my string has a specific number of characters.
Use this method to get "(whitespaces) John"
NSString *string = #"Hello John";
NSUInteger spacePosition = [string rangeOfString:#" "].location;
NSMutableString *newString = [[NSMutableString alloc]init ];
for (int i=0; i<spacePosition; i++)
[newString appendString:#" "];
NSString *otherPartofString = [string substringFromIndex:(spacePosition)];
[newString appendString:otherPartofString];
NSLog(#"new String is '%#'",newString);
[newString release];
You can use [string substringWithRange:NSMakeRange(start, count)], that way you will only get a new string that you can use for displaying.
you can do like this:
find the position of space between two strings like this:
NSUInteger spacePosition = [string rangeOfString:#" "].location
then use:
NSString *otherPartofString = [string substringFromIndex:(spacePosition+1)];

How to get the first N words from a NSString in Objective-C?

What's the simplest way, given a string:
NSString *str = #"Some really really long string is here and I just want the first 10 words, for example";
to result in an NSString with the first N (e.g., 10) words?
EDIT: I'd also like to make sure it doesn't fail if the str is shorter than N.
If the words are space-separated:
NSInteger nWords = 10;
NSRange wordRange = NSMakeRange(0, nWords);
NSArray *firstWords = [[str componentsSeparatedByString:#" "] subarrayWithRange:wordRange];
if you want to break on all whitespace:
NSCharacterSet *delimiterCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSArray *firstWords = [[str componentsSeparatedByCharactersInSet:delimiterCharacterSet] subarrayWithRange:wordRange];
Then,
NSString *result = [firstWords componentsJoinedByString:#" "];
While Barry Wark's code works well for English, it is not the preferred way to detect word breaks. Many languages, such as Chinese and Japanese, do not separate words using spaces. And German, for example, has many compounds that are difficult to separate correctly.
What you want to use is CFStringTokenizer:
CFStringRef string; // Get string from somewhere
CFLocaleRef locale = CFLocaleCopyCurrent();
CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, string, CFRangeMake(0, CFStringGetLength(string)), kCFStringTokenizerUnitWord, locale);
CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone;
unsigned tokensFound = 0, desiredTokens = 10; // or the desired number of tokens
while(kCFStringTokenizerTokenNone != (tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) && tokensFound < desiredTokens) {
CFRange tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
CFStringRef tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, string, tokenRange);
// Do something with the token
CFShow(tokenValue);
CFRelease(tokenValue);
++tokensFound;
}
// Clean up
CFRelease(tokenizer);
CFRelease(locale);
Based on Barry's answer, I wrote a function for the sake of this page (still giving him credit on SO)
+ (NSString*)firstWords:(NSString*)theStr howMany:(NSInteger)maxWords {
NSArray *theWords = [theStr componentsSeparatedByString:#" "];
if ([theWords count] < maxWords) {
maxWords = [theWords count];
}
NSRange wordRange = NSMakeRange(0, maxWords - 1);
NSArray *firstWords = [theWords subarrayWithRange:wordRange];
return [firstWords componentsJoinedByString:#" "];
}
Here's my solution, derived from the answers given here, for my own problem of removing the first word from a string...
NSMutableArray *words = [NSMutableArray arrayWithArray:[lowerString componentsSeparatedByString:#" "]];
[words removeObjectAtIndex:0];
return [words componentsJoinedByString:#" "];