Parsing in order with rangeOfString: - objective-c

The issue I have is that I want to parse strings in order, so for instance, parsing "one three two", adding that to another string, and printing "one three two". I'm using rangeOfString:, but when I parse that string, it returns "one two three". I know that the order of parsing in my case is the placement of the if statements, but how do I parse that string in order? Here is my code:
NSString *string = #"one three two";
NSString *newString;
if ([string rangeOfString:#"one"].location != NSNotFound)
{
newString = [newString stringByAppendingString:#"one"];
}
if ([string rangeOfString:#"two"].location != NSNotFound)
{
newString = [newString stringByAppendingString:#"two"];
}
if ([string rangeOfString:#"three"].location != NSNotFound)
{
newString = [newString stringByAppendingString:#"three"];
}
NSLog(#"%#",newString);

You are doing this wrong, you should use componentsSeparatedByString: and sorting:
NSString *stringWithNumbersOrdered(NSString *input)
{
static NSArray *numberStrings = nil;
if (!numberStrings)
{
numberStrings = [NSArray arrayWithObjects:#"zero", #"one", #"two", #"three", #"four", #"five", #"six", #"seven", #"eight", #"nine", /* etc. */ nil];
}
NSArray *components = [input componentsSeparatedByString:#" "];
NSArray *componentsSorted = [components sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
int value1 = [numberStrings indexOfObject:obj1];
int value2 = [numberStrings indexOfObject:obj2];
return value1 - value2;
}];
return [componentsSorted componentsJoinedByString:#" "];
}

Related

Formatting NSString, Objective-C

What would be the best way to transform NSStrings like these (mixed case)
#"Hello lorem ipsum";
#"i am a test";
to these (camel case without spaces)
#"helloLoremIpsum";
#"iAmATest";
Try this
Using For Loop
- (NSString *)camelCased:(NSString *)aString {
NSMutableString *result = [NSMutableString new];
NSArray *words = [aString componentsSeparatedByString: #" "];
for (NSUInteger i = 0; i < words.count; i++) {
if (i==0) {
[result appendString:([words[i] lowercaseString])];
}
else {
[result appendString:([words[i] capitalizedString])];
}
}
return result;
}
Using Block
- (NSString *)camelCasedUsingBlock:(NSString *)aString {
NSMutableArray *words = [[NSMutableArray alloc] init];
[[aString componentsSeparatedByString:#" "] enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) {
if (idx == 0) {
[words addObject:[anObject lowercaseString]];
}
else{
[words addObject:[anObject capitalizedString]];
}
}];
return [words componentsJoinedByString:#""];
}
NSLog(#"%#",[self camelCased:#"Hello lorem ipsum"]);//helloLoremIpsum
NSLog(#"%#",[self camelCased:#"i am a test"]);//iAmATest
It's overkill but TransformerKit has a bunch of NSValueTransformers that can be used, one is for camel casing. The relevant file is TTTStringTransformers.m if you want to build your own solution for lightness.

Objective-C: How to find the most common string in an array?

I have an array of strings from an online database that I trying to determine the most commonly used word. The values inside the arrays will vary but I want to check the most common words of whatever collection or words I'm using. If theoretically I had an array of the following...
NSArray *stringArray = [NSArray arrayWithObjects:#"Duck", #"Duck", #"Duck", #"Duck", #"Goose"];
How do I iterate through this array to determine the most common string, which would obviously be "Duck"?
Simplest way is probably NSCountedSet:
NSCountedSet* stringSet = [[NSCountedSet alloc] initWithArray:strings];
NSString* mostCommon = nil;
NSUInteger highestCount = 0;
for(NSString* string in stringSet) {
NSUInteger count = [stringSet countForObject:string];
if(count > highestCount) {
highestCount = count;
mostCommon = string;
}
}
You can use the word as a key into a dictionary.
NSMutableDictionary *words = [NSMutableDictionary dictionary];
for (NSString *word in stringArray) {
if (!words[word]) {
[words setValue:[NSDecimalNumber zero] forKey:word];
}
words[word] = [words[word] decimalNumberByAdding:[NSDecimalNumber one]];
}
Now iterate through words and find the key with the highest value.
NSString *mostCommon;
NSDecimalNumber *curMax = [NSDecimalNumber zero];
for (NSString *key in [words allKeys]) {
if ([words[key] compare:curMax] == NSOrderedDescending) {
mostCommon = key;
curMax = word[key];
}
}
NSLog(#"Most Common Word: %#", mostCommon);
EDIT: Rather than looping through the array once then looping separately through the sorted dictionary, I think we can do better and do it all in a single loop.
NSString *mostCommon;
NSDecimalNumber *curMax = [NSDecimalNumber zero];
NSMutableDictionary *words = [NSMutableDictionary dictionary];
for (NSString *word in stringArray) {
if (!words[word]) {
[words setValue:[NSDecimalNumber zero] forKey:word];
}
words[word] = [words[word] decimalNumberByAdding:[NSDecimalNumber one]];
if ([words[word] compare:curMax] == NSOrderedDescending) {
mostCommon = word;
curMax = words[word];
}
}
NSLog(#"Most Common Word: %#", mostCommon);
This should be significantly faster than my answer pre-edit, though I don't know how it compares to using the NSCountedSet answer.
Try using NSPredicate.
NSUInteger count=0;
NSString *mostCommonStr;
for(NSString *strValue in stringArray) {
NSUInteger countStr=[[stringArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self MATCHES[CD] %#, strValue]]count];
if(countStr > count) {
count=countStr;
mostCommonStr=strValue;
}
}
NSLog(#"The most commonstr is %#",mostCommonStr);

Simplest way to concatenate objective-C strings and achieve grammatical correctness (with 'and' conjunction)

What is the easiest and best way in Objective-C to combine a list (NSArray) of NSStrings into a single NSString separated by commas, with the grammatically correct terminal conjunction ", and " before the final item of the list?
NSArray *anArray = [NSArray arrayWithObjects:#"milk", #"butter", #"eggs", #"spam", nil];
From this array, I want the NSString #"milk, butter, eggs, and spam".
More generally, if the list is more than two items long, I want ", " between every item except the last and second-to-last (which should have ", and "). If the list is two items long, I want just the ' and ' with no comma. If the list is one item long, I want the single string from the array.
I like something as simple as:
NSString *newString = [anArray componentsJoinedByString:#", "];
But this of course omits the 'and' conjunction.
Is there a simpler and/or faster Objective-C way than the following:
- (NSString *)grammaticallyCorrectStringFromArrayOfStrings:(NSArray *)anArray {
if (anArray == nil) return nil;
int arrayCount = [anArray count];
if (arrayCount == 0) return #"";
if (arrayCount == 1) return [anArray objectAtIndex:0];
if (arrayCount == 2) return [anArray componentsJoinedByString:#" and "];
// arrayCount > 2
NSString *newString = #"";
for (NSString *thisString in anArray) {
if (thisString != [anArray objectAtIndex:0] && thisString != [anArray lastObject]) {
newString = [newString stringByAppendingString:#", "];
}
else if (thisString == [anArray lastObject]) {
newString = [newString stringByAppendingString:#", and "];
}
newString = [newString stringByAppendingString:thisString];
}
return newString;
}
For the loop, I'd probably do something like
NSMutableString *newString = [NSMutableString string];
NSUInteger lastIndex = arrayCount - 1;
[anArray enumerateObjectsUsingBlock:^(NSString *thisString, NSUInteger idx, BOOL *stop) {
if (idx != 0)
[newString appendString:#","];
if (idx == lastIndex)
[newString appendString:#" and "];
[newString appendString:thisString];
}];
Though I guess that's not really less lines.

Check for substring in string with NSString from NSArray?

So pretty much I want to check if my NSString from my NSArray is a substring of my string named imageName.
So lets say this:
My Image name is: picture5of-batman.png
My Array contains strings and one of them is: Batman
So pretty much I want to eliminate the: picture5of- part of the image name and replace it with the NSString from the NSArray.
This is how I try to do it but it never makes it to the if statement. And no my Array is not nil either. Here is the code:
for (NSString *string in superheroArray) {
if ([string rangeOfString:imageName].location != NSNotFound) {
//Ok so some string in superheroArray is equal to the file name of the image
imageName = [imageName stringByReplacingOccurrencesOfString:#"" withString:string
options:NSCaseInsensitiveSearch range:NSMakeRange(0, string.length)];
}
}
Edit1: This still does not work
for (NSString *string in superheroArray) {
if ([imageName rangeOfString:string options:NSCaseInsensitiveSearch].location != NSNotFound) {
//Ok so some string in superheroArray is equal to the file name of the image
imageName = string;
//HOW ABOUT THAT FOR EFFICIENCY :P
}
}
[imageName rangeOfString:string options: NSCaseInsensitiveSearch]
I don't see why it's not working in your code, maybe split the NSString stuff from the NSRage test.
but this work here :
NSArray *ar = [NSArray arrayWithObjects:#"Batman", #"Maurice", nil];
__block NSString *imageName = #"picture5of-batman.png";
__block NSUInteger theIndex = -1;
[ar enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSRange r = [imageName rangeOfString: obj
options: NSCaseInsensitiveSearch];
if (r.location != NSNotFound)
{
theIndex = idx;
NSString *str = [imageName pathExtension];
imageName = [(NSString *)obj stringByAppendingPathExtension:str];
// you found it, so you can stop now
*stop = YES;
}
}];
if (theIndex != -1)
{
NSLog(#"The index is : %d and new imageName == %#", theIndex, imageName);
}
And here is the NSLog statement :
2011-12-10 23:04:28.967 testSwitch1[2493:207] The index is : 0 and new imageName == Batman.png

How to get values after "\n" character?

I want to take all values after a new line character \n from my string. How can I get those values?
Try this:
NSString *substring = nil;
NSRange newlineRange = [yourString rangeOfString:#"\n"];
if(newlineRange.location != NSNotFound) {
substring = [yourString substringFromIndex:newlineRange.location];
}
Take a look at method componentsSeparatedByString here.
A quick example taken from reference:
NSString *list = #"Norman, Stanley, Fletcher";
NSArray *listItems = [list componentsSeparatedByString:#", "];
this will produce a NSArray with strings separated: { #"Norman", #"Stanley", #"Fletcher" }
Here is similar function which splits the string by delimeter and return array with two trimmed values.
NSArray* splitStrByDelimAndTrim(NSString *string, NSString *delim)
{
NSRange range = [string rangeOfString: delim];
NSString *first;
NSString *second;
if(range.location == NSNotFound)
{
first = #"";
second = string;
}
else
{
first = [string substringToIndex: range.location];
first = [first stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
second = [string substringFromIndex: range.location + 1];
second = [second stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
}
return [NSArray arrayWithObjects: first, second, nil];
}