What NSString do I put for return?
The answer I am looking for is 1 cheese OR 2 cheeses
- (NSString *) numberOfCheesesStringWithCheeseCount:(NSUInteger)cheeseCount
{
if (cheeseCount == 1) {
/* WORK HERE, ASSUMING THERE IS 1 CHEESE */
NSString *phrase = [NSString stringWithFormat:#"%ld", (long)cheeseCount];
NSLog(#"%# cheese", phrase);
} else {
/* WORK HERE, ASSUMING THERE ARE 2+ CHEESES */
NSString *phrase2 = [NSString stringWithFormat:#"%ld", (long)cheeseCount];
NSLog(#"%# cheeses", phrase2);
}
/*
(You will learn more about if/else statements in the next checkpoint.)
*/
return ;
}
How about this?
- (NSString *) numberOfCheesesStringWithCheeseCount:(NSUInteger)cheeseCount
{
NSString *result;
if (cheeseCount == 1)
{
//No real point in building this string piecewise. It will always be
//the same thing, "1 cheese".
result = #"1 cheese";
}
else
{
/* WORK HERE, ASSUMING THERE ARE 2+ CHEESES */
NSString *result = [NSString stringWithFormat:#"%ld cheeses", (long)cheeseCount];
}
NSLog(#"Result = %#", result);
return result;
}
This is not how I’d do this for real, but in the context of your exercise, this would be a good time to learn about variable scope. What you should do is declare an NSString outside of the conditional. That way, when you assign it or change it in the conditional it retains its value. Then assign the phrase inside the conditionals. After you are done, return the phrase.
- (NSString *)numberOfCheesesStringWithCheeseCount:(NSUInteger)cheeseCount
{
NSString *phrase = nil;
if (cheeseCount == 1)
{
phrase = [NSString stringWithFormat:#"%ld cheese", (long)cheeseCount];
NSLog(#"%#", phrase);
}
else
{
phrase = [NSString stringWithFormat:#"%ld cheeses", (long)cheeseCount];
NSLog(#"%#", phrase);
}
return phrase;
}
I honestly don't see the point in having the whole if else statement this can be shortened to just an if statement. I'd recommend changing to something like:
- (NSString *)numberOfCheesesStringWithCheeseCount:(NSUInteger)cheeseCount
{
// We setup our string (phrase) already with the value "1 Cheese"
NSString *phrase = #"1 Cheese";
if (cheeseCount > 1) {
// If the value of cheeseCount is greater than 1 then we update our value.
phrase = [NSString stringWithFormat:#"%ld cheeses", (long)cheeseCount];
}
// Return our value for phrase.
return phrase;
}
This code reads some much simpler then the whole if else statement.
- (NSString *)numberOfCheesesStringWithCheeseCount:(NSUInteger)cheeseCount
{
NSString *phrase = [NSString stringWithFormat:#"%ld cheeses", (long)cheeseCount];
if (cheeseCount == 1)
{
phrase = [NSString stringWithFormat:#"%ld cheese", (long)cheeseCount];
}
NSLog(#"%#", phrase);
return phrase;
}
Related
Trying to create a method with only one parameter that may accept NSString or int.
Here's what I did so far:
-(NSString*)LocalizeNumber:(void*)TheNumber{
BOOL IsVarInt = false;
NSString * Num = "";
if(IsVarInt){
Num = [NSString stringWithFormat:#"%i",(int)TheNumber];
}else{
Num = [NSString stringWithFormat:#"%#",(__bridge NSString*)TheNumber];
}
//rest of code...
}
And this is how I call this method:
if passing int:
[self LocalizeNumber:(void*)150];
if passing NSString:
[self LocalizeNumber:#"150"];
The problem is that I still don't know how to know if the parameter "TheNumber" is NSString or int.
Thank you.
While I suggest you rethink your approach, your goal can be achieved as follows:
- (NSString *)localizeNumber:(id)number {
NSString *num = nil;
if ([number isKindOfClass:[NSNumber class]]) {
num = [number stringValue];
} else if ([number isKindOfClass:[NSString class]]) {
num = number;
} else {
// oops - bad value
}
// rest of code using num
}
Then you can call the method as follows:
NSString *someString = #"Hello";
NSString *result = [self localizeNumber:someString];
or:
int someInt = 42;
NSString *result = [self localizeNumber:#(someInt)];
You cannot tell between an object type and a plain primitive. However, you can easily tell between two object types if you pass an int passed in NSNumber wrapper, like this:
-(NSString*)LocalizeNumber:(id)TheNumber {
NSString *Num = #"";
if ([TheNumber isKindOfClass:[NSSTRING class]]) {
Num = [NSString stringWithFormat:#"%#", TheNumber];
} else if ([TheNumber isKindOfClass:[NSNumber class]]) {
Num = [NSString stringWithFormat:#"%i",[TheNumber intValue]];
}
//rest of code...
}
You could use categories to add -stringValue to NSString:
#implementation NSString (LocalizedNumber)
-(NSString*)stringValue
{
return self ;
}
#end
Then you can call:
NSString * localizedNumber = [<number or string object> stringValue]
There is no safe way to tell an int from an NSString reference.
This is a question on how to code this efficiently with as little as code possible. It already works but I need to incoporate the paramenter numberOfShapes. That if 1 returns ■, if 2 ■■, if 3 ■■■ etc...
I could do some extra if statemets and extra return statements. If Square->if number = 1> return ■, if number >2 return ■■ etc.. But that is a whole lot of code for something very simple.
What is the best way of coding this with the least amount of code?
- (NSString *)getShape: (NSNumber *)shape numberOfShapes: (NSNumber *)number
{
if ([shape isEqualToNumber:[NSNumber numberWithInt:SQUARE]]) return #"■";
if ([shape isEqualToNumber:[NSNumber numberWithInt:CIRCLE]]) return #"●";
if ([shape isEqualToNumber:[NSNumber numberWithInt:TRIANGLE]]) return #"▲";
return #"?";
}
Largely a question of taste unless you have some really heavy performance requirements.
One way to do it could be to set up a dictionary with the map from numbers to glyphs.
Assuming that you have a static variable glyphs, initialize it in the class' initialize method:
static NSDictionary *glyphs;
+ (void)initialize
{
glyphs = #{
#(SQUARE):#"■",
#(CIRCLE):#"●",
#(TRIANGLE):#"▲"
};
}
Then all you have to do is:
- (NSString *)shapeForNumber:(NSInteger)shape
{
NSString *glyph = [glyphs objectForKey: [NSNumber numberWithInteger: shape]];
return glyph ? glyph : #"?";
}
- (NSString *)getShape: (NSNumber *)shape numberOfShapes: (NSNumber *)number
{
unsigned shapeInt = [shape unsignedIntValue];
if (shapeInt >= 3)
return #"?";
NSString *shapeStr = [#"■●▲" substringWithRange:NSMakeRange(shapeInt, 1)];
// Add autorelease here, if using MRR...
NSMutableString *result = [[NSMutableString alloc] init];
unsigned numberInt = [number unsignedIntValue];
for (unsigned i = 0; i < numberInt; i++)
[result appendString:shapeStr];
return result;
}
I don't see the point of using NSNumber objects to pass parameters like this, as they can't do anything that a simple NSUInteger or unsigned can, and are more expensive to use.
Is there a demonstrated performance problem with the code? Otherwise, I think a switch is pretty clear. Or, fewer lines and O(1) is ...
// declare this earlier
static NSArray *shapeChars = #[ #"■", #"●" /* etc. */ ];
// then
return [shapeChars objectAtIndex:[shape intValue]];
Enter the concept of loops. Also, why do you use NSNumbers for this? Plain old ints are good enough.
- (NSString *)getShape:(int)shape numberOfShapes:(int)number
{
if (shape == SQUARE]) return [self shapeRepeated:#"■" nTimes:number];
if (shape == CIRCLE]]) return [self shapeRepeated:#"●" nTimes:number];
if (shape == TRIANGLE]]) return [self shapeRepeated:#"▲" nTimes:number];
return #"?";
}
- (NSString *)shapeRepeated:(NSString *)shape nTimes:(int)n
{
return [#"" stringByPaddingToLength:n withString:shape startingAtIndex:0];
}
- (NSString *)getShape: (NSNumber *)shape numberOfShapes: (NSNumber *)number
{
switch([number intValue]): {
case SQUARE: return #"■";
case CIRCLE: return #"●";
case TRIANGLE: return #"▲";
default: return #"?";
}
}
To incorporate "number":
- (NSString *)getShape: (NSNumber *)shape numberOfShapes: (NSNumber *)number
{
NSString* result = nil;
switch([number intValue]): {
case SQUARE: result = #"■"; break;
case CIRCLE: result = #"●"; break;
case TRIANGLE: result= #"▲"; break;
default: result = #"?";
}
NSString* realResult = #"";
for (int i = 0; i < number; i++) {
realResult = [realResult stringByAppendingString:result];
}
return realResult;
}
You could neaten it up by using a char value for result, but I'm too lazy.
I have an NSString called query which contains ~10 characters.
I would like to check to see if a second NSString called word contains all of the characters in query, or some characters, but no other characters which aren't specified in query.
Also, if there is only one occurrence of the character in the query, there can only be one occurrence of the character in the word.
Please could you tell me how to do this?
NSString *query = #"ABCDEFJAKSUSHFKLAFIE";
NSString *word = #"fearing"; //would pass as NO as there is no 'n' in the query var.
The following answers the first half:
NSCharacterSet *nonQueryChars = [[NSCharacterSet characterSetWithCharactersInString:[query lowercaseString]] invertedSet];
NSRange badCharRange = [[word lowercaseString] rangeOfCharacterFromSet:nonQueryChars];
if (badCharRange.location == NSNotFound) {
// word only has characters in query
} else {
// found unwanted characters in word
}
I need to think about the second half of the requirement.
Ok, the following code should fulfill both requirements:
- (NSCountedSet *)wordLetters:(NSString *)text {
NSCountedSet *res = [NSCountedSet set];
for (NSUInteger i = 0; i < text.length; i++) {
[res addObject:[text substringWithRange:NSMakeRange(i, 1)]];
}
return res;
}
- (void)checkWordAgainstQuery {
NSString *query = #"ABCDEFJAKSUSHFKLAFIE";
NSString *word = #"fearing";
NSCountedSet *queryLetters = [self wordLetters:[query lowercaseString]];
NSCountedSet *wordLetters = [self wordLetters:[word lowercaseString]];
BOOL ok = YES;
for (NSString *wordLetter in wordLetters) {
int wordCount = [wordLetters countForObject:wordLetter];
// queryCount will be 0 if this word letter isn't in query
int queryCount = [queryLetters countForObject:wordLetter];
if (wordCount > queryCount) {
ok = NO;
break;
}
}
if (ok) {
// word matches against query
} else {
// word has extra letter or too many of a matching letter
}
}
How can I optimise out this nested for loop?
The program should go through each word in the array created from the word text file, and if it's greater than 8 characters, add it to the goodWords array. But the caveat is that I only want the root word to be in the goodWords array, for example:
If greet is added to the array, I don't want greets or greetings or greeters, etc.
NSString *string = [NSString stringWithContentsOfFile:#"/Users/james/dev/WordParser/word.txt" encoding:NSUTF8StringEncoding error:NULL];
NSArray *words = [string componentsSeparatedByString:#"\r\n"];
NSMutableArray *goodWords = [NSMutableArray array];
BOOL shouldAddToGoodWords = YES;
for (NSString *word in words)
{
NSLog(#"Word: %#", word);
if ([word length] > 8)
{
NSLog(#"Word is greater than 8");
for (NSString *existingWord in [goodWords reverseObjectEnumerator])
{
NSLog(#"Existing Word: %#", existingWord);
if ([word rangeOfString:existingWord].location != NSNotFound)
{
NSLog(#"Not adding...");
shouldAddToGoodWords = NO;
break;
}
}
if (shouldAddToGoodWords)
{
NSLog(#"Adding word: %#", word);
[goodWords addObject:word];
}
}
shouldAddToGoodWords = YES;
}
How about something like this?
//load the words from wherever
NSString * allWords = [NSString stringWithContentsOfFile:#"/usr/share/dict/words"];
//create a mutable array of the words
NSMutableArray * words = [[allWords componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] mutableCopy];
//remove any words that are shorter than 8 characters
[words filterUsingPredicate:[NSPredicate predicateWithFormat:#"length >= 8"]];
//sort the words in ascending order
[words sortUsingSelector:#selector(caseInsensitiveCompare:)];
//create a set of indexes (these will be the non-root words)
NSMutableIndexSet * badIndexes = [NSMutableIndexSet indexSet];
//remember our current root word
NSString * currentRoot = nil;
NSUInteger count = [words count];
//loop through the words
for (NSUInteger i = 0; i < count; ++i) {
NSString * word = [words objectAtIndex:i];
if (currentRoot == nil) {
//base case
currentRoot = word;
} else if ([word hasPrefix:currentRoot]) {
//word is a non-root word. remember this index to remove it later
[badIndexes addIndex:i];
} else {
//no match. this word is our new root
currentRoot = word;
}
}
//remove the non-root words
[words removeObjectsAtIndexes:badIndexes];
NSLog(#"%#", words);
[words release];
This runs very very quickly on my machine (2.8GHz MBP).
A Trie seems suitable for your purpose. It is like a hash, and is useful for detecting if a given string is a prefix of an already seen string.
I used an NSSet to ensure that you only have 1 copy of a word added at a time. It will add a word if the NSSet does not already contain it. It then checks to see if the new word is a substring for any word that has already been added, if true then it won't add the new word. It's case-insensitive as well.
What I've written is a refactoring of your code. It's probably not that much faster but you really do want a tree data structure if you want to make it a lot faster when you want to search for words that have already been added to your tree.
Take a look at RedBlack Trees or B-Trees.
Words.txt
objective
objectively
cappucin
cappucino
cappucine
programme
programmer
programmatic
programmatically
Source Code
- (void)addRootWords {
NSString *textFile = [[NSBundle mainBundle] pathForResource:#"words" ofType:#"txt"];
NSString *string = [NSString stringWithContentsOfFile:textFile encoding:NSUTF8StringEncoding error:NULL];
NSArray *wordFile = [string componentsSeparatedByString:#"\n"];
NSMutableSet *goodWords = [[NSMutableSet alloc] init];
for (NSString *newWord in wordFile)
{
NSLog(#"Word: %#", newWord);
if ([newWord length] > 8)
{
NSLog(#"Word '%#' contains 8 or more characters", newWord);
BOOL shouldAddWord = NO;
if ( [goodWords containsObject:newWord] == NO) {
shouldAddWord = YES;
}
for (NSString *existingWord in goodWords)
{
NSRange textRange = [[newWord lowercaseString] rangeOfString:[existingWord lowercaseString]];
if( textRange.location != NSNotFound ) {
// newWord contains the a substring of existingWord
shouldAddWord = NO;
break;
}
NSLog(#"(word:%#) does not contain (substring:%#)", newWord, existingWord);
shouldAddWord = YES;
}
if (shouldAddWord) {
NSLog(#"Adding word: %#", newWord);
[goodWords addObject:newWord];
}
}
}
NSLog(#"***Added words***");
int count = 1;
for (NSString *word in goodWords) {
NSLog(#"%d: %#", count, word);
count++;
}
[goodWords release];
}
Output:
***Added words***
1: cappucino
2: programme
3: objective
4: programmatic
5: cappucine
I'm looking for a simple, efficient way to convert strings in CamelCase to underscore notation (i.e., MyClassName -> my_class_name) and back again in Objective C.
My current solution involves lots of rangeOfString, characterAtIndex, and replaceCharactersInRange operations on NSMutableStrings, and is just plain ugly as hell :) It seems that there must be a better solution, but I'm not sure what it is.
I'd rather not import a regex library just for this one use case, though that is an option if all else fails.
Chris's suggestion of RegexKitLite is good. It's an excellent toolkit, but this could be done pretty easily with NSScanner. Use -scanCharactersFromSet:intoString: alternating between +uppercaseLetterCharacterSet and +lowercaseLetterCharacterSet. For going back, you'd use -scanUpToCharactersFromSet: instead, using a character set with just an underscore in it.
How about these:
NSString *MyCamelCaseToUnderscores(NSString *input) {
NSMutableString *output = [NSMutableString string];
NSCharacterSet *uppercase = [NSCharacterSet uppercaseLetterCharacterSet];
for (NSInteger idx = 0; idx < [input length]; idx += 1) {
unichar c = [input characterAtIndex:idx];
if ([uppercase characterIsMember:c]) {
[output appendFormat:#"_%#", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
} else {
[output appendFormat:#"%C", c];
}
}
return output;
}
NSString *MyUnderscoresToCamelCase(NSString *underscores) {
NSMutableString *output = [NSMutableString string];
BOOL makeNextCharacterUpperCase = NO;
for (NSInteger idx = 0; idx < [underscores length]; idx += 1) {
unichar c = [underscores characterAtIndex:idx];
if (c == '_') {
makeNextCharacterUpperCase = YES;
} else if (makeNextCharacterUpperCase) {
[output appendString:[[NSString stringWithCharacters:&c length:1] uppercaseString]];
makeNextCharacterUpperCase = NO;
} else {
[output appendFormat:#"%C", c];
}
}
return output;
}
Some drawbacks are that they do use temporary strings to convert between upper and lower case, and they don't have any logic for acronyms, so myURL will result in my_u_r_l.
Try this magic:
NSString* camelCaseString = #"myBundleVersion";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(?<=[a-z])([A-Z])|([A-Z])(?=[a-z])" options:0 error:nil];
NSString *underscoreString = [[regex stringByReplacingMatchesInString:camelCaseString options:0 range:NSMakeRange(0, camelCaseString.length) withTemplate:#"_$1$2"] lowercaseString];
NSLog(#"%#", underscoreString);
Output: my_bundle_version
If your concern is just the visibility of your code, you could make a category for NSString using the methods you've designed already. That way, you only see the ugly mess once. ;)
For instance:
#interface NSString(Conversions) {
- (NSString *)asCamelCase;
- (NSString *)asUnderscored;
}
#implementation NSString(Conversions) {
- (NSString *)asCamelCase {
// whatever you came up with
}
- (NSString *)asUnderscored {
// whatever you came up with
}
}
EDIT: After a quick Google search, I couldn't find any way of doing this, even in plain C. However, I did find a framework that could be useful. It's called RegexKitLite. It uses the built-in ICU library, so it only adds about 20K to the final binary.
Here's my implementation of Rob's answer:
#implementation NSString (CamelCaseConversion)
// Convert a camel case string into a dased word sparated string.
// In case of scanning error, return nil.
// Camel case string must not start with a capital.
- (NSString *)fromCamelCaseToDashed {
NSScanner *scanner = [NSScanner scannerWithString:self];
scanner.caseSensitive = YES;
NSString *builder = [NSString string];
NSString *buffer = nil;
NSUInteger lastScanLocation = 0;
while ([scanner isAtEnd] == NO) {
if ([scanner scanCharactersFromSet:[NSCharacterSet lowercaseLetterCharacterSet] intoString:&buffer]) {
builder = [builder stringByAppendingString:buffer];
if ([scanner scanCharactersFromSet:[NSCharacterSet uppercaseLetterCharacterSet] intoString:&buffer]) {
builder = [builder stringByAppendingString:#"-"];
builder = [builder stringByAppendingString:[buffer lowercaseString]];
}
}
// If the scanner location has not moved, there's a problem somewhere.
if (lastScanLocation == scanner.scanLocation) return nil;
lastScanLocation = scanner.scanLocation;
}
return builder;
}
#end
Here's yet another version based on all the above. This version handles additional forms. In particular, tested with the following:
camelCase => camel_case
camelCaseWord => camel_case_word
camelURL => camel_url
camelURLCase => camel_url_case
CamelCase => camel_case
Here goes
- (NSString *)fromCamelCaseToDashed3 {
NSMutableString *output = [NSMutableString string];
NSCharacterSet *uppercase = [NSCharacterSet uppercaseLetterCharacterSet];
BOOL previousCharacterWasUppercase = FALSE;
BOOL currentCharacterIsUppercase = FALSE;
unichar currentChar = 0;
unichar previousChar = 0;
for (NSInteger idx = 0; idx < [self length]; idx += 1) {
previousChar = currentChar;
currentChar = [self characterAtIndex:idx];
previousCharacterWasUppercase = currentCharacterIsUppercase;
currentCharacterIsUppercase = [uppercase characterIsMember:currentChar];
if (!previousCharacterWasUppercase && currentCharacterIsUppercase && idx > 0) {
// insert an _ between the characters
[output appendString:#"_"];
} else if (previousCharacterWasUppercase && !currentCharacterIsUppercase) {
// insert an _ before the previous character
// insert an _ before the last character in the string
if ([output length] > 1) {
unichar charTwoBack = [output characterAtIndex:[output length]-2];
if (charTwoBack != '_') {
[output insertString:#"_" atIndex:[output length]-1];
}
}
}
// Append the current character lowercase
[output appendString:[[NSString stringWithCharacters:¤tChar length:1] lowercaseString]];
}
return output;
}
If you are concerned with the speed of your code you probably want to write a more performant version of the code:
- (nonnull NSString *)camelCaseToSnakeCaseString {
if ([self length] == 0) {
return #"";
}
NSMutableString *output = [NSMutableString string];
NSCharacterSet *digitSet = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *uppercaseSet = [NSCharacterSet uppercaseLetterCharacterSet];
NSCharacterSet *lowercaseSet = [NSCharacterSet lowercaseLetterCharacterSet];
for (NSInteger idx = 0; idx < [self length]; idx += 1) {
unichar c = [self characterAtIndex:idx];
// if it's the last one then just append lowercase of character
if (idx == [self length] - 1) {
if ([uppercaseSet characterIsMember:c]) {
[output appendFormat:#"%#", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
}
else {
[output appendFormat:#"%C", c];
}
continue;
}
unichar nextC = [self characterAtIndex:(idx+1)];
// this logic finds the boundaries between lowercase/uppercase/digits and lets the string be split accordingly.
if ([lowercaseSet characterIsMember:c] && [uppercaseSet characterIsMember:nextC]) {
[output appendFormat:#"%#_", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
}
else if ([lowercaseSet characterIsMember:c] && [digitSet characterIsMember:nextC]) {
[output appendFormat:#"%#_", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
}
else if ([digitSet characterIsMember:c] && [uppercaseSet characterIsMember:nextC]) {
[output appendFormat:#"%#_", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
}
else {
// Append lowercase of character
if ([uppercaseSet characterIsMember:c]) {
[output appendFormat:#"%#", [[NSString stringWithCharacters:&c length:1] lowercaseString]];
}
else {
[output appendFormat:#"%C", c];
}
}
}
return output;
}
I have combined the answers found here into my refactoring library, es_ios_utils. See NSCategories.h:
#property(nonatomic, readonly) NSString *asCamelCaseFromUnderscores;
#property(nonatomic, readonly) NSString *asUnderscoresFromCamelCase;
Usage:
#"my_string".asCamelCaseFromUnderscores
yields #"myString"
Please push improvements!
I happened upon this question looking for a way to convert Camel Case to a spaced, user displayable string. Here is my solution which worked better than replacing #"_" with #" "
- (NSString *)fromCamelCaseToSpaced:(NSString*)input {
NSCharacterSet* lower = [NSCharacterSet lowercaseLetterCharacterSet];
NSCharacterSet* upper = [NSCharacterSet uppercaseLetterCharacterSet];
for (int i = 1; i < input.length; i++) {
if ([upper characterIsMember:[input characterAtIndex:i]] &&
[lower characterIsMember:[input characterAtIndex:i-1]])
{
NSString* soFar = [input substringToIndex:i];
NSString* left = [input substringFromIndex:i];
return [NSString stringWithFormat:#"%# %#", soFar, [self fromCamelCaseToSpaced:left]];
}
}
return input;
}
OK guys. Here is an all regex answer, which I consider the only true way:
Given:
NSString *MYSTRING = "foo_bar";
NSRegularExpression *_toCamelCase = [NSRegularExpression
regularExpressionWithPattern:#"(_)([a-z])"
options:NSRegularExpressionCaseInsensitive error:&error];
NSString *camelCaseAttribute = [_toCamelCase
stringByReplacingMatchesInString:MYSTRING options:0
range:NSMakeRange(0, attribute.length)
withTemplate:#"\\U$2"];
Yields fooBar.
Conversely:
NSString *MYSTRING = "fooBar";
NSRegularExpression *camelCaseTo_ = [NSRegularExpression
regularExpressionWithPattern:#"([A-Z])"
options:0 error:&error];
NSString *underscoreParsedAttribute = [camelCaseTo_
stringByReplacingMatchesInString:MYSTRING
options:0 range:NSMakeRange(0, attribute.length)
withTemplate:#"_$1"];
underscoreParsedAttribute = [underscoreParsedAttribute lowercaseString];
Yields: foo_bar.
\U$2 replaces second capture group with upper-case version of itself :D
\L$1 however, oddly, does not replace the first capture group with a lower-case version of itself :( Not sure why, it should work. :/