NSMutableString to NSMutableArray - objective-c

I have a NSMutableString with a bunch of floating point numbers.
I need to convert them to NSMutableArray but in groups of 3:
0.015637 0.0205293 0.0270841 0.0157598 0.0202236 0.0272967 0.013217 0.0205293 0.0283439 0.0115028 0.0205293 0.0290539 0.0107803 0.0202236 0.0296187 -0.029892 0.0194995 0.0108798 -0.0299242 0.0191089 0.0108915 0.0243682 0.0194995 0.0204474 0.0307989 0.0205293 -0.00543068 0.0313996 0.0202236 0.00274711 -0.0157598 0.0202236 0.0272967 -0.0180789 0.0202236 0.0258193 -0.0182457 0.0194995 -0.0260576 -0.0182654 0.0191089 -0.0260857 -0.0134582 0.0191089
The numbers are all floating point values and there can be over 30 000 of them or more.
I have tried this but it's not working…
NSArray *contentarray = [content componentsSeparatedByString: #" "];
for(NSNumber * withfastenumeration in contentarray)
{
[XYZarray addObject: withfastenumeration];
}
Hi Guys,
I wanted to add a bit more information to this question since you guys have been so helpful. Okay so this is a COLLADA XML based project, and it involves vectors so hence the massive array of floating point numbers.
I got to the point where I am parsing with NSXMLParser and isolating the points. They are given however, in a blank format in the XML file as X, Y, Z in repetitive order, only separated by spaces.
I am writing a machining algorithm so I need these numbers in an array, but I need the array to look like:
X0.015637 Y0.0205293 Z0.0270841
X0.0157598 Y0.0202236 Z0.0272967
Once I have that, then I can manipulate all these numbers in a similar fashion.
Again, thanks for these solutions and Happy Holidays!

componentsSeparatedByString: returns an array of NSString, not an array of NSNumber. You need to write code to convert each component to a number. For example, you can send doubleValue to each component to get back a double, and then use #(...) to wrap the double in an NSNumber.
NSArray *words = [content componentsSeparatedByString:#" "];
NSMutableArray *triples = [NSMutableArray arrayWithCapacity:words.count / 3];
for (NSUInteger i = 0, count = words.count; i < count; i += 3) {
NSArray *triple = #[
#([words[i+0] doubleValue]),
#([words[i+1] doubleValue]),
#([words[i+2] doubleValue])
];
[triples addObject:triple];
}
Note that -[NSString doubleValue] doesn't do locale-aware parsing. If you need that, you'll need to use an NSScanner or NSNumberFormatter. Also, if you are having trouble with the memory used by the array of 30000+ substrings, use an NSScanner to process the substrings one at a time without creating the big array.
Here's how you do it with NSScanner:
NSScanner *scanner = [NSScanner scannerWithString:content];
// or use localizedScannerWithString: for locale-aware parsing
NSMutableArray *triples = [NSMutableArray arrayWithCapacity:words.count / 3];
double x, y, z;
while ([scanner scanDouble:&x] && [scanner scanDouble:&y] && [scanner scanDouble:&z]) {
NSArray *triple = #[ #(x), #(y), #(z) ];
[triples addObject:triple];
}

1st idea
what about this?
NSMutableString *_string = // your raw string as in your question...
NSLock *_lock = [[NSLock alloc] init];
NSMutableArray *_array = [NSMutableArray array];
[[_string componentsSeparatedByString:#" "] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([_lock tryLock]) [_array addObject:#([obj doubleValue])], [_lock unlock];
}];
2nd idea
that would be a better solution if you want to work with the numbers in group of 3 elegantly:
put these in the .h file:
typedef struct {
Float64 a;
Float64 b;
Float64 c;
} FloatNumbers;
static inline FloatNumbers FloatNumbersMake(Float64 a, Float64 b, Float64 c) {
FloatNumbers fn; fn.a = a; fn.b = b; fn.c = c; return fn;
}
static inline NSString * NSStringFromFloatNumbers(FloatNumbers fn) {
return [NSString stringWithFormat:#"{%f, %f, %f}", fn.a, fn.b, fn.c];
}
static inline FloatNumbers FloatNumbersFromString(NSString * string) {
#try {
NSArray *_array = [[string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"{}"]] componentsSeparatedByString:#", "];
return FloatNumbersMake([[_array objectAtIndex:0] doubleValue], [[_array objectAtIndex:1] doubleValue], [[_array objectAtIndex:2] doubleValue]);
}
#catch (NSException *exception) {
return FloatNumbersMake(0.f, 0.f, 0.f);
}
}
and these into any methods of the .m file (where you'd like to parse the raw string):
NSMutableString *_string = // your raw string with the numbers...
NSError *_error;
NSLock *_lock = [[NSLock alloc] init];
NSMutableArray *_mutableArray = [NSMutableArray array];
NSRegularExpression *_regExp = [NSRegularExpression regularExpressionWithPattern:#"(([\\d\\.\\+-]+\\s?){0,3})" options:0 error:&_error];
if (!_error) {
[_regExp enumerateMatchesInString:_string options:NSMatchingReportProgress range:NSMakeRange(0, _string.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
FloatNumbers _floatNumbers = FloatNumbersMake(MAXFLOAT, MAXFLOAT, MAXFLOAT);
#try {
NSArray *_groupOfNumbers = [[_string substringWithRange:result.range] componentsSeparatedByString:#" "];
_floatNumbers.a = [[_groupOfNumbers objectAtIndex:0] doubleValue];
_floatNumbers.b = [[_groupOfNumbers objectAtIndex:1] doubleValue];
_floatNumbers.c = [[_groupOfNumbers objectAtIndex:2] doubleValue];
}
#catch (NSException *exception) {
}
#finally {
if ([_lock tryLock]) [_mutableArray addObject:NSStringFromFloatNumbers(_floatNumbers)], [_lock unlock];
*stop = (flags == NSMatchingHitEnd);
}
}];
} else {
NSLog(#"%#", _error);
}
the _mutableArray has the numbers, each object is a group of 3; here is an example of how you can read back the desired group of 3 numbers from the array and you are able to work with the values after.
// reading the numbers back
FloatNumbers _secondGroupOf3Numbers = FloatNumbersFromString([_mutableArray objectAtIndex:1]);
NSLog(#"a : %f, b : %f, c : %f", _secondGroupOf3Numbers.a, _secondGroupOf3Numbers.b, _secondGroupOf3Numbers.c);
therefore that will log you the second group of 3 numbers, like:
a : 0.015760, b : 0.020224, c : 0.027297
(bear in mind: those are rounded values for the debug-console only, the float numbers are the same as they were parsed.)

If I understand right you want to receive an array of strings and each string must contain 3 numbers?
Let's use regexp:
NSString *inputString = #"0.015637 0.0205293 0.0270841 0.0157598 0.0202236 0.0272967 0.013217 0.0205293 0.0283439 0.0115028 0.0205293 0.0290539 0.0107803 0.0202236 0.0296187 -0.029892 0.0194995 0.0108798 -0.0299242 0.0191089 0.0108915 0.0243682 0.0194995 0.0204474 0.0307989 0.0205293 -0.00543068 0.0313996 0.0202236 0.00274711 -0.0157598 0.0202236 0.0272967 -0.0180789 0.0202236 0.0258193 -0.0182457 0.0194995 -0.0260576 -0.0182654 0.0191089 -0.0260857 -0.0134582 0.0191089 0.0191089";
NSError *error;
// Creating regexp that will split input string to substring with 3 numbers
NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:#"(([\\d\\.-]+\\s?){3})"
options:0
error:&error];
// TODO: Handle error if appear
//
NSArray *matches = [regExp matchesInString:inputString
options:0
range:NSMakeRange(0, [inputString length])];
NSMutableArray *result = [NSMutableArray new];
for (NSTextCheckingResult *match in matches) {
// Get the matching string
NSString *substring = [inputString substringWithRange:[match range]];
// Trim whitespace at the end
substring = [substring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[result addObject:substring];
}

Related

How to multiply respective objects of NSArray and get the sum?

I have one array with data A=[a,b,c] and another with data B=[d,e,f]. I need to perform this type of operation a.d+ b.e+c.f (Note=Here (.) denotes multplication)and get the result. How can i do that using Objective-C?
Thanks in advance.
Define the function that does the multiplication and addition like this:
- (double)multiply:(NSArray <NSNumber *> *)vector1 withVector:(NSArray <NSNumber *> *)vector2 {
NSAssert(vector1.count == vector2.count, #"Both arrays should contain the same number of elements");
__block double result = 0;
[vector1 enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
double first = obj.doubleValue;
double second = vector2[idx].doubleValue;
result += first * second;
}];
return result;
}
This uses a block enumeration method on NSArray which gives me in index and a value, which I can use to get the value at the same index in the second array. Note also that I am using a typed array, so I don't have to cast the values to NSNumbers when using them.
Now you can just use the function:
NSArray *a = #[#1, #2, #3];
NSArray *b = #[#4, #5, #6];
NSArray *c = #[#1, #1, #1];
double res1 = [self multiply:a withVector:b]; // => 32.000000
double res2 = [self multiply:b withVector:c]; // => 15.000000
double res3 = [self multiply:c withVector:a]; // => 6.000000
NSNumber *myNum1 = [NSNumber numberWithInt:1];
NSNumber *myNum2 = [NSNumber numberWithInt:2];
NSNumber *myNum3 = [NSNumber numberWithInt:3];
NSArray *a = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
NSArray *b = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
int sum=0;
for (int i=0; i<[a count]; i++) {
NSLog(#"%#", (NSNumber*)[a objectAtIndex:i]);
sum =sum +[(NSNumber*)[a objectAtIndex:i] intValue]*[(NSNumber*)[b objectAtIndex:i] intValue];
}
NSLog(#"Sum is %d", sum);
Hope this helps

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
)

Sort characters in NSString into alphabetical order

I'm trying to re-arrange words into alphabetical order. For example, tomato would become amoott, or stack would become ackst.
I've found some methods to do this in C with char arrays, but I'm having issues getting that to work within the confines of the NSString object.
Is there an easier way to do it within the NSString object itself?
You could store each of the string's characters into an NSArray of NSNumber objects and then sort that. Seems a bit expensive, so I would perhaps just use qsort() instead.
Here it's provided as an Objective-C category (untested):
NSString+SortExtension.h:
#import <Foundation/Foundation.h>
#interface NSString (SortExtension)
- (NSString *)sorted;
#end
NSString+SortExtension.m:
#import "NSString+SortExtension.h"
#implementation NSString (SortExtension)
- (NSString *)sorted
{
// init
NSUInteger length = [self length];
unichar *chars = (unichar *)malloc(sizeof(unichar) * length);
// extract
[self getCharacters:chars range:NSMakeRange(0, length)];
// sort (for western alphabets only)
qsort_b(chars, length, sizeof(unichar), ^(const void *l, const void *r) {
unichar left = *(unichar *)l;
unichar right = *(unichar *)r;
return (int)(left - right);
});
// recreate
NSString *sorted = [NSString stringWithCharacters:chars length:length];
// clean-up
free(chars);
return sorted;
}
#end
I think separate the string to an array of string(each string in the array contains only one char from the original string). Then sort the array will be OK. This is not efficient but is enough when the string is not very long. I've tested the code.
NSString *str = #"stack";
NSMutableArray *charArray = [NSMutableArray arrayWithCapacity:str.length];
for (int i=0; i<str.length; ++i) {
NSString *charStr = [str substringWithRange:NSMakeRange(i, 1)];
[charArray addObject:charStr];
}
NSString *sortedStr = [[charArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] componentsJoinedByString:#""];
// --------- Function To Make an Array from String
NSArray *makeArrayFromString(NSString *my_string) {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < my_string.length; i ++) {
[array addObject:[NSString stringWithFormat:#"%c", [my_string characterAtIndex:i]]];
}
return array;
}
// --------- Function To Sort Array
NSArray *sortArrayAlphabetically(NSArray *my_array) {
my_array= [my_array sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
return my_array;
}
// --------- Function Combine Array To Single String
NSString *combineArrayIntoString(NSArray *my_array) {
NSString * combinedString = [[my_array valueForKey:#"description"] componentsJoinedByString:#""];
return combinedString;
}
// Now you can call the functions as in below where string_to_arrange is your string
NSArray *blowUpArray;
blowUpArray = makeArrayFromString(string_to_arrange);
blowUpArray = sortArrayAlphabetically(blowUpArray);
NSString *arrayToString= combineArrayIntoString(blowUpArray);
NSLog(#"arranged string = %#",arrayToString);
Just another example using NSMutableString and sortUsingComparator:
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:#"tomat"];
[mutableString appendString:#"o"];
NSLog(#"Orignal string: %#", mutableString);
NSMutableArray *charArray = [NSMutableArray array];
for (int i = 0; i < mutableString.length; ++i) {
[charArray addObject:[NSNumber numberWithChar:[mutableString characterAtIndex:i]]];
}
[charArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
if ([obj1 charValue] < [obj2 charValue]) return NSOrderedAscending;
return NSOrderedDescending;
}];
[mutableString setString:#""];
for (int i = 0; i < charArray.count; ++i) {
[mutableString appendFormat:#"%c", [charArray[i] charValue]];
}
NSLog(#"Sorted string: %#", mutableString);
Output:
Orignal string: tomato
Sorted string: amoott

Get matched string from two NSArrays

How can I save the string that match from one NSArray with one index difference in NSMutableArray?
For example, there are three "apple", four "pineapple", six "banana", two "cocoa" and the rest of words dont have duplicate(s) in the nsarray, i would like to know if the nsarray has at least two same words. If yes, I would like to save "apple", "pineapple, "banana" and "cocoa" once in nsmutablearray. If there are other alike words, I would like to add them to namutablearray too.
My code (which still doesn't work properly);
NSArray *noWords = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"words" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL]
componentsSeparatedByString:#"\n"]];
NSUInteger scount = [noWords count];
int ii = 0;
NSString *stringline;
for (ii; ii < scount; ii++)
{
stringline = [noWords objectAtIndex:ii];
NSLog(#"stringline : %# ", stringline);
}
int i = 1;
NSString *line;
for (i ; i < 10; i++)
{
line = [noWords objectAtIndex:i];
NSLog (#"line : %# ", line);
NSMutableArray *douwords = [NSMutableArray array];
if ([stringline isEqualToString:line])
{
NSString *newword;
for (newword in douwords)
{
[douwords addObject:newword];
NSLog (#"detected! %# ", douwords);
}
}
}
Here's a solution using two sets:
- (NSArray *)getDuplicates:(NSArray *)words
{
NSMutableSet *dups = [NSMutableSet set],
*seen = [NSMutableSet set];
for (NSString *word in words) {
if ([seen containsObject:word]) {
[dups addObject:word];
}
[seen addObject:word];
}
return [dups allObjects];
}
Assuming NSSet uses hash tables behind the scenes (which I'm betting it does), this is going to be faster than the previously suggested O(n^2) solution.
Here's something off the top of my head:
NSMutableSet* duplicates = [NSMutableSet set];
NSArray* words = [NSArray arrayWithObjects:#"Apple", #"Apple", #"Orange", #"Apple", #"Orange", #"Pear", nil];
[words enumerateObjectsUsingBlock:^(NSString* str, NSUInteger idx, BOOL *stop) {
for (int i = idx + 1; i < words.count; i++) {
if ([str isEqualToString:[words objectAtIndex:i]]) {
[duplicates addObject:str];
break;
}
}
}];
NSLog(#"Dups: %#", [duplicates allObjects]); // Prints "Apple" and "Orange"
The use of an NSSet, as opposed to an NSArray, ensures strings are not added more than once. Obviously, there are optimizations that could be done, but it should be a good starting point.
I assume that you want to count appearances of words in your array and output those with a count of more than one. A basic and verbose way to do that would be:
// Make an array of words - some duplicates
NSArray *wordList = [[NSArray alloc] initWithObjects:
#"Apple", #"Banana", #"Pencil",
#"Steve Jobs", #"Kandahar",
#"Apple", #"Banana", #"Apple",
#"Pear", #"Pear", nil];
// Make an mutable dictionary - the key will be a word from the list
// and the value will be a number representing the number of times the
// word appears in the original array. It starts off empty.
NSMutableDictionary *wordCount = [[NSMutableDictionary alloc] init];
// In turn, take each word in the word list...
for (NSString *s in wordList) {
int count = 1;
// If the word is already in the dictionary
if([wordCount objectForKey:s]) {
// Increse the count by one
count = [[wordCount objectForKey:s] intValue] + 1;
}
// Save the word count in the dictionary
[wordCount setObject:[NSNumber numberWithInt:count] forKey:s];
}
// For each word...
for (NSString *s in [wordCount keysOfEntriesPassingTest:
^(id key, id obj, BOOL *stop) {
if ([obj intValue] > 1) return YES; else return NO;
}]) {
// print the word and the final count
NSLog(#"%2d %#", [[wordCount objectForKey:s] intValue], s);
}
The output would be:
3 Apple
2 Pear
2 Banana