Is there a simple way to split a NSString into an array of characters? - objective-c

Is there a simple way to split a NSString into an array of characters? It would actually be best if the resulting type were a collection of NSString's themselves, just one character each.
Yes, I know I can do this in a loop, but I'm wondering if there is a faster way to do this with any existing methods or functions the way you can with LINQ in C#.
e.g.
// I have this...
NSString * fooString = #"Hello";
// And want this...
NSArray * fooChars; // <-- Contains the NSStrings, #"H", #"e", #"l", #"l" and #"o"

You could do something like this (if you want to use enumerators)
NSString *fooString = #"Hello";
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[fooString length]];
[fooString enumerateSubstringsInRange:NSMakeRange(0, fooString.length)
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[characters addObject:substring];
}];
And if you really wanted it in an NSArray finally
NSArray *fooChars = [NSArray arrayWithArray:characters];

Be sure to care about that some characters like emoji and others may span a longer range than just one index.
Here's a category method for NSString
#implementation (SplitString)
- (NSArray *)splitString
{
NSUInteger index = 0;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.length];
while (index < self.length) {
NSRange range = [self rangeOfComposedCharacterSequenceAtIndex:index];
NSString *substring = [self substringWithRange:range];
[array addObject:substring];
index = range.location + range.length;
}
return array;
}
#end

convert it to NSData the [data bytes] will have a C string in the encoding that you pick [data length] bytes long.

Try this
NSMutableArray *array = [NSMutableArray array];
NSString *str = #"Hello";
for (int i = 0; i < [str length]; i++) {
NSString *ch = [str substringWithRange:NSMakeRange(i, 1)];
[array addObject:ch];
}

Related

NSString to NSArray and editing every object

I have an NSString filled with objects seperated by a comma
NSString *string = #"1,2,3,4";
I need to seperate those numbers and store then into an array while editing them, the result should be
element 0 = 0:1,
element 1 = 1:2,
element 2 = 2:3,
element 3 = 3:4.
How can i add those to my objects in the string ??
Thanks.
P.S : EDIT
I already did that :
NSString *string = #"1,2,3,4";
NSArray *array = [string componentsSeparatedByString:#","];
[array objectAtIndex:0];//1
[array objectAtIndex:1];//2
[array objectAtIndex:2];//3
[array objectAtIndex:3];//4
I need the result to be :
[array objectAtIndex:0];//0:1
[array objectAtIndex:1];//1:2
[array objectAtIndex:2];//2:3
[array objectAtIndex:3];//3:4
In lieu of a built in map function (yey for Swift) you would have to iterate over the array and construct a new array containing the desired strings:
NSString *string = #"1,2,3,4";
NSArray *array = [string componentsSeparatedByString:#","];
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:array.count];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[newArray addObject:[NSString stringWithFormat:#"%lu:%#", (unsigned long)idx, obj]];
}];
The first thing you need to do is separate the string into an array of component parts - NSString has a handy method for that : '-componentsSeparatedByString'. Code should be something like this :
NSArray *components = [string componentsSeparatedByString:#","];
So that gives you 4 NSString objects in your array. You could then iterate through them to make compound objects in your array, though you arent exactly clear how or why you need those. Maybe something like this :
NSMutableArray *resultItems = [NSMutableArray array];
for (NSString *item in components)
{
NSString *newItem = [NSString stringWithFormat:#"%#: ... create your new item", item];
[resultItems addObject:newItem];
}
How about this?
NSString *string = #"1,2,3,4";
NSArray *myOldarray = [string componentsSeparatedByString:#","];
NSMutableArray *myNewArray = [[NSMutableArray alloc] init];
for (int i=0;i<myOldarray.count;i++) {
[myNewArray addObject:[NSString stringWithFormat:#"%#:%d", [myOldarray objectAtIndex:i], ([[myOldarray objectAtIndex:i] intValue]+1)]];
}
// now you have myNewArray what you want.
This is with consideration that in array you want number:number+1

How can I convert an NSRange to a delimited string of its values?

Given an NSRange, such as:
NSRange range = NSMakeRange(1, 22);
What's the best way to convert it to a comma-separated string of its values?
#"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22"
The best I could come up with was to iterate over the range and insert its values into an NSArray, and then call -componentsJoinedByString: on the array. But that seems pretty wasteful, not to mention inelegant. Is there no better way?
My version using an array:
NSMutableArray *vals = [NSMutableArray arrayWithCapacity:range.length];
for (NSUInteger i = range.location; i < range.length; i++){
[vals addObject:#(i)];
}
NSString *string = [vals componentsJoinedByString:#","];
You can use NSIndexSet with indexSetWithIndexesInRange: to generate a list of values, and then iterate through them with enumerateIndexesUsingBlock:. E.g.
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
NSMutableArray *indices = [NSMutableArray array];
[indexSet enumerateIndexesUsingBlock:^(NSUInteger i, BOOL *stop) {
[indices addObject:#(i)];
}];
NSString *string = [indices componentsJoinedByString:","];
NSMutableString *string=[#"" mutableCopy];
for (int i = range.location; i<range.length-1; i++){
[string appendFormat:#"%d,", i];
}
[string appendString#"%d", range.length-1];
If you want to hide the code, you can turn it into a function that would take the range and turn it into a string, that way this is hidden from your code. Or maybe turn it into a NSString class method, something like
[NSString stringWithRangeValues:range];
That would be like:
+ (NSString *)stringWithRangeValues:(NSRange)range{
NSMutableString *string=[#"" mutableCopy];
for (int i = range.location; i<range.lenght-1; i++){
[string appendFormat:#"%d,", i];
}
[string appendString#"%d", range.length-1];
return [NSString stringWithString:string];
}

How to print the reverse of NSString in objective c without using componentsSeparatedByString method?

I want to make a method which gives reverse of string.suppose I pass a NSString "Welcome to Objective C" in method and that method return a reverse of string like "C Objective to Welcome" not "C evitcejbO ot emocleW" without the use of componentsSeparatedByString method.
Is it possible to do with Objective c..?
Please help.
You can enumerate strings by words.
NSString *string = #"Welcome to Objective-C!";
NSMutableArray *words = [NSMutableArray array];
[string enumerateLinguisticTagsInRange:NSMakeRange(0, [string length])
scheme:NSLinguisticTagSchemeTokenType
options:0
orthography:nil
usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
[array addObject:[string substringWithRange:tokenRange]];
}];
NSMutableString *reverseString = [[NSMutableString alloc] init];
for (NSString *word in [words reverseObjectEnumerator]){
[reverse appendString:word];
}
NSLog(#"%#", reverseString);
This will print...
"!C-Objective to Welcome"
You can change the options to omit whitespaces and stuff...
I used below method for reversing string in iOS
- (NSString *)reverseString:(NSString *)stringToReverse
{
NSMutableString *reversedString = [NSMutableString stringWithCapacity:[stringToReverse length]];
[stringToReverse enumerateSubstringsInRange:NSMakeRange(0, [stringToReverse length])
options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reversedString appendString:substring];
}];
return reversedString;
}
Sorry I misread your question earlier. I did it using a series of loops, my answer is messier than Fogmeister but I wanted to give it a shot to see if I could do it.
NSString *str = #"This is a test";
NSMutableArray *array = [[NSMutableArray alloc] init];
for(int i = 0; i < [str length]; i++)
{
char sTest = [str characterAtIndex:i];
if(sTest == ' ')
{
[array addObject:[NSNumber numberWithInt:i]];
}
}
NSInteger iNext = [[array objectAtIndex:[array count]-1] integerValue];
iNext+=1;
if(iNext < [str length])
{
[array addObject:[NSNumber numberWithInt:iNext]];
}
NSMutableArray *wordArray = [[NSMutableArray alloc] init];
for(int i = 0; i < [array count]; i++)
{
if (i == 0)
{
int num = [[array objectAtIndex:i] integerValue];
NSString *s = [[str substringFromIndex:0] substringToIndex:num];
[wordArray addObject:s];
}
else if(i == [array count]-1)
{
int prev = [[array objectAtIndex:i-1] integerValue]+1;
int num = [str length];
NSString *s = [[str substringToIndex:num] substringFromIndex:prev];
[wordArray addObject:s];
}
else
{
int prev = [[array objectAtIndex:i-1] integerValue]+1;
int num = [[array objectAtIndex:i] integerValue];
NSString *s = [[str substringToIndex:num] substringFromIndex:prev];
[wordArray addObject:s];
}
}
NSMutableArray *reverseArray = [[NSMutableArray alloc]init];
for(int i = [wordArray count]-1; i >= 0; i--)
{
[reverseArray addObject:[wordArray objectAtIndex:i]];
}
NSLog(#"%#", reverseArray);
Here i have done with replacing character with minimal number of looping. log(n/2).
NSString *string=#"Happy World";
NSInteger lenth=[string length];
NSInteger halfLength=[string length]/2;
for(int i=0;i<halfLength;i++)
{
NSString *leftString=[NSString stringWithFormat:#"%c",[string characterAtIndex:i]];
NSString *rightString=[NSString stringWithFormat:#"%c",[string characterAtIndex:(lenth-i-1)]];
string= [string stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:rightString];
string=[string stringByReplacingCharactersInRange:NSMakeRange((lenth-i-1), 1) withString:leftString];
}
NSLog(#"%#",string);
Try This , It's working perfect as per your expectation ,
Call Function :-
[self reversedString:#"iOS"];
Revers String Function :-
-(void)reversedString :(NSString *)reversStr
{ // reversStr is "iOS"
NSMutableString *reversedString = [NSMutableString string];
NSInteger charIndex = [reversStr length];
while (charIndex > 0) {
charIndex--;
NSRange subStrRange = NSMakeRange(charIndex, 1);
[reversedString appendString:[reversStr substringWithRange:subStrRange]];
}
NSLog(#"%#", reversedString); // outputs "SOi"
}
Hope So this is help for some one .
There is no API to do that, if that's what you are asking.
You can always iterate through the string looking for white spaces (or punctuation, it depends on your needs), identify the words and recompose your "reversed" message manually.

Spliting string to array by constant number

I'v been trying to split string to array of components by number, but have no idea how to do it. I know that each components lenght is 9 except the last one. But there is no separation between them. Maybe anyone would know how could i make this split possible?
string : E44000000R33000444V33441
And i'd like to get array with: E44000000 R33000444 V33441
in past I'v used this method, but i guess there should be a way to separate by constant number. Any ideas
NSArray *myWords = [message componentsSeparatedByString:#";"];
Please try the below code.
NSString *stringTest = #"E44000000R33000444V33441323";
NSMutableArray *arrayTest = [NSMutableArray array];
while([stringTest length] > 8) {
[arrayTest addObject:[NSString stringWithString:[stringTest substringToIndex:9]]];
stringTest = [stringTest substringFromIndex:9];
}
NSLog(#"arrayTest - %#", arrayTest);
Try this one..
NSString *mainString=#"E44000000R33000444V";
NSMutableArray *brokenString=[NSMutableArray new];
int start=0;
for (; start<mainString.length-9; start+=9) {
[brokenString addObject:[mainString substringWithRange:NSMakeRange(start, 9)]];
}
[brokenString addObject:[mainString substringFromIndex:start]];
NSLog(#"->%#",brokenString);
Output is :
->(
E44000000,
R33000444,
V
)
I investigated the NSString, and i didn't found any function like that. But you can create a category of NSString and put this function in that category and you can use as a NSString instance method.
- (NSArray *) componentSaparetedByLength:(NSUInteger) length{
NSMutableArray *array = [NSMutableArray new];
NSRange range = NSMakeRange(0, length);
NSString *subString = nil;
while (range.location + range.length <= self.length) {
subString = [self substringWithRange:range];
[array addObject:subString];
//Edit
range.location = range.length + range.location;
//Edit
range.length = length;
}
if(range.location<self.length){
subString = [self substringFromIndex:range.location];
[array addObject:subString];
}
return array;
}
You can get the substring upto the characters which you want in a loop(string length) & pass the next index for getting the next substring. After getting each substring you can add it to the array.
Used SubstringToIndex & SubstringFromIndex functions to get the substring.
Also not an requirement here, I want to propose a solution that is capable of handling characters from more sophisticated script systems, like surrogate pairs, base characters plus combining marks, Hangul jamo, and Indic consonant clusters.
#interface NSString (Split)
-(NSArray *)arrayBySplittingWithMaximumSize:(NSUInteger)size
options:(NSStringEnumerationOptions) option;
#end
#implementation NSString (Split)
-(NSArray *)arrayBySplittingWithMaximumSize:(NSUInteger)size
options:(NSStringEnumerationOptions) option
{
NSMutableArray *letterArray = [NSMutableArray array];
[self enumerateSubstringsInRange:NSMakeRange(0, [self length])
options:(option)
usingBlock:^(NSString *substring,
NSRange substringRange,
NSRange enclosingRange,
BOOL *stop) {
[letterArray addObject:substring];
}];
NSMutableArray *array = [NSMutableArray array];
[letterArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx%size == 0) {
[array addObject: [NSMutableString stringWithCapacity:size]];
}
NSMutableString *string = [array objectAtIndex:[array count]-1];
[string appendString:obj];
}];
return array;
}
#end
usage
NSArray *array = [#"E44000000R33000444V33441" arraysBySplittingWithMaximumSize:9
options:NSStringEnumerationByComposedCharacterSequences];
results in:
(
E44000000,
R33000444,
V33441
)

iOS - Most efficient way to find word occurrence count in a string

Given a string, I need to obtain a count of each word that appears in that string. To do so, I extracted the string into an array, by word, and searched that way, but I have the feeling that searching the string directly is more optimal. Below is the code that I originally wrote to solve the problem. I'm up for suggestions on better solutions though.
NSMutableDictionary *sets = [[NSMutableDictionary alloc] init];
NSString *paragraph = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"text" ofType:#"txt"] encoding:NSUTF8StringEncoding error:NULL];
NSMutableArray *words = [[[paragraph lowercaseString] componentsSeparatedByString:#" "] mutableCopy];
while (words.count) {
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
NSString *search = [words objectAtIndex:0];
for (unsigned i = 0; i < words.count; i++) {
if ([[words objectAtIndex:i] isEqualToString:search]) {
[indexSet addIndex:i];
}
}
[sets setObject:[NSNumber numberWithInt:indexSet.count] forKey:search];
[words removeObjectsAtIndexes:indexSet];
}
NSLog(#"%#", sets);
Example:
Starting string:
"This is a test. This is only a test."
Results:
"This" - 2
"is" - 2
"a" - 2
"test" - 2
"only" - 1
This is exactly what an NSCountedSet is for.
You need to break the string apart into words (which iOS is nice enough to give us a function for so that we don't have to worry about punctuation) and just add each of them to the counted set, which keeps track of the number of times each object appears in the set:
NSString *string = #"This is a test. This is only a test.";
NSCountedSet *countedSet = [NSCountedSet new];
[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
options:NSStringEnumerationByWords | NSStringEnumerationLocalized
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
// This block is called once for each word in the string.
[countedSet addObject:substring];
// If you want to ignore case, so that "this" and "This"
// are counted the same, use this line instead to convert
// each word to lowercase first:
// [countedSet addObject:[substring lowercaseString]];
}];
NSLog(#"%#", countedSet);
// Results: 2012-11-13 14:01:10.567 Testing App[35767:fb03]
// <NSCountedSet: 0x885df70> (a [2], only [1], test [2], This [2], is [2])
If I had to guess, I would say NSRegularExpression for that. Like this:
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
options:0
range:NSMakeRange(0, [string length])];
That snippet was taken from here.
Edit 1.0:
Based on what Sir Till said:
NSString *string = #"This is a test, so it is a test";
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSArray *arrayOfWords = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
for (NSString *word in arrayOfWords)
{
if ([dictionary objectForKey:word])
{
NSNumber *numberOfOccurences = [dictionary objectForKey:word];
NSNumber *increment = [NSNumber numberWithInt:(1 + [numberOfOccurences intValue])];
[dictionary setValue:increment forKey:word];
}
else
{
[dictionary setValue:[NSNumber numberWithInt:1] forKey:word];
}
}
You should be careful with:
Punctuation signs. (near other words)
UpperCase words vs lowerCase words.
I think that's really bad idea that you trying to search a words among the long paragraph with a loop. You should use a regular expression to do that! I know it's not easy at first time to learn it but it's really worth to know it! Take look at this case Use regular expression to find/replace substring in NSString