Objective-C: Find consonants in string - iphone

I have a string that contains words with consonants and vowels. How can I extract only consonants from the string?
NSString *str = #"consonants.";
Result must be:
cnsnnts

You could make a character set with all the vowels (#"aeiouy")
+ (id)characterSetWithCharactersInString:(NSString *)aString
then use the
- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set
method.
EDIT: This will only remove vowels at the beginning and end of the string as pointed out in the other post, what you could do instead is use
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
then stick the components back together. You may also need to include capitalized versions of the vowels in the set, and if you want to also deal with accents (à á è è ê ì etc...) you'll probably have to include that also.

Unfortunately stringByTrimmingCharactersInSet wont work as it only trim leading and ending characters, but you could try using a regular expression and substitution like this:
[[NSRegularExpression
regularExpressionWithPattern:#"[^bcdefghjklmnpqrstvwx]"
options:NSRegularExpressionCaseInsensitive
error:NULL]
stringByReplacingMatchesInString:str
options:0
range:NSMakeRange(0, [str length])
withTemplate:#""]
You probably want to tune the regex and options for your needs.

Possible, for sure not-optimal, solution. I'm printing intermediate results for your learning. Take care of memory allocation (I didn't care). Hopefully someone will send you a better solution, but you can copy and paste this for the moment.
NSString *test = #"Try to get all consonants";
NSMutableString *found = [[NSMutableString alloc] init];
NSInteger loc = 0;
NSCharacterSet *consonants = [NSCharacterSet characterSetWithCharactersInString:#"bcdfghjklmnpqrstvwxyz"];
while(loc!=NSNotFound && loc<[test length]) {
NSRange r = [[test lowercaseString] rangeOfCharacterFromSet:consonants options:0 range:NSMakeRange(loc, [test length]-loc)];
if(r.location!=NSNotFound) {
NSString *temp = [test substringWithRange:r];
NSLog(#"Range: %# Temp: %#",NSStringFromRange(r), temp);
[found appendString:temp];
loc=r.location+r.length;
} else {
loc=NSNotFound;
}
}
NSLog(#"Found: %#",found);

Here is a NSString category that does the job:
- (NSString *)consonants
{
NSString *result = [NSString stringWithString:self];
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:#"aeiou"];
while(1)
{
NSRange range = [result rangeOfCharacterFromSet:characterSet options:NSCaseInsensitiveSearch];
if(range.location == NSNotFound)
break;
result = [result stringByReplacingCharactersInRange:range withString:#""];
}
return result;
}

Related

Substring after substring in NSString

I am new in objective and I'm facing my first problem, and I can not continue my first project.
it's quite simple, I have a NSString :
NSString *myString = #"<font face='Helvetica' size=25 color='#d79198'> Here is some text !</font>";
what I want to do is to get the value of the size "25" which is always 2 char long, so I can calculate my UILabel size.
i know how to detect if there is the substring I am looking for "size=" using :
if ([string rangeOfString:#"bla"].location == NSNotFound)
but I have not found or not understand how to extract the string #"size=XX" and then get the XX as a NSString from *myString
Thank for any help.
NSString *myString = #"<font face='Helvetica' size=25 color='#d79198'> Here is some text !</font>";
NSRange range = [myString rangeOfString:#"size="];
if (range.location != NSNotFound)
{
NSLog(#"Found \"size=\" at %d", range.location);
NSString *sizeString = [myString substringWithRange:NSMakeRange(range.location+5, 2)];
NSLog(#"sizeString: %#", sizeString);
}
This should do the trick. You could also at the end do this: int sizeFont = [sizeString intValue];
NSString *myString = #"<font face='Helvetica' size=25 color='#d79198'> Here is some text !</font>";
if ([myString rangeOfString:#"size"].location != NSNotFound)
{
myString = [myString substringFromIndex:[myString rangeOfString:#"size"].location];
myString = [myString substringToIndex:[myString rangeOfString:#" "].location]; // Now , myString ---> size=25 color='#d79198'> Here is some text !</font>
myString = [myString substringFromIndex:[myString length]-2];// Now, myString ---> size=25
NSLog(#"myString -- %#",myString); // Now, myString ---> 25
}
If you have string like stack:overflow then use it as follow :
NSString *Base=#"stack:overflow"
NSString *one = [[Base componentsSeparatedByString:#":"] objectAtIndex:0];
NSString *two = [[Base componentsSeparatedByString:#":"] objectAtIndex:1];
In this case one = stack and two=overflow
Part of an HTML page? Then use the tool that is designed for the task.
You could calculate the range of the number yourself or use a very simple regular expression to get the substring, something like
(?<=size\=)\d*
This means that you are searching for digits (\d*) that is preceded by "size=" ((?<=size\=))
Which using NSRegularExpression would be
NSError *error = NULL;
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:#"(?<=size\\=)\\d*"
options:0
error:&error];
NSTextCheckingResult *match =
[regex firstMatchInString:myString
options:0
range:NSMakeRange(0, [myString length])];
NSString *sizeText = [myString substringWithRange:match.range];
Finally you should convert the text "25" into a number using
NSInteger size = [sizeText integerValue];
Use componentsSeparatedByString: method...
NSString *myString = #"<font face='Helvetica' size=25 color='#d79198'> Here is some text !</font>";
NSString *theSizeString = [[[[myString componentsSeparatedByString:#" "] objectAtIndex:2] componentsSeparatedByString:#"="] objectAtIndex:1];
NSLog(#"The sizestring:%#",theSizeString);
I think it will be helpful to you.
You can get the range of the string #"size=". The range has location and length. So what you need next is to call on the myString the substringWithRange: method. The parameter would be an NSRage starting from the location+length of #"size=" and length of 2.

Replacing instances of a character with two different characters in Objective-C

I have a huge amount of NSStrings in a database that get passed to a view controller in an iOS app. They are formatted as "This is a message with $specially formatted$ content".
However, I need to change the '$' at the start of the special formatting with a '[' and the '$' at the end with ']'. I have a feeling I can use an NSScanner but so far all of my attempts have produced wackily concatenated strings!
Is there a simple way to recognise a substring encapsulated by '$' and swap them out with start/end characters? Please note that a lot of the NSStrings have multiple '$' substrings.
Thanks!
You can use regular expressions:
NSMutableString *str = [#"Hello $World$, foo $bar$." mutableCopy];
NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:#"\\$([^$]*)\\$"
options:0
error:NULL];
[regex replaceMatchesInString:str
options:0
range:NSMakeRange(0, [str length])
withTemplate:#"[$1]"];
NSLog(#"%#", str);
// Output:
// Hello [World], foo [bar].
The pattern #"\\$([^$]*)\\$" searches for
$<zero_or_more_characters_which_are_not_a_dollarsign>$
and all occurrences are then replaced by [...]. The pattern contains so many backslashes because the $ must be escaped in the regular expression pattern.
There is also stringByReplacingMatchesInString if you want to create a new string instead of modifying the original string.
I think replaceOccurrencesOfString: won't work cause you have start$ and end$.
But if you seperate the Strings with [string componentsSeperatedByString:#"$"] you get an Array of substrings, so every second string is your "$specially formatted$"-string
This should work!
NSString *str = #"This is a message with $specially formatted$ content";
NSString *original = #"$";
NSString *replacement1 = #"[";
NSString *replacement2 = #"]";
BOOL start = YES;
NSRange rOriginal = [str rangeOfString: original];
while (NSNotFound != rOriginal.location) {
str = [str stringByReplacingCharactersInRange: rOriginal withString:(start?replacement1:replacement2)];
start = !start;
rOriginal = [str rangeOfString: original];
}
NSLog(#"%#", str);
Enjoy Programming!
// string = #"This is a $special markup$ sentence."
NSArray *components = [string componentsSeparatedByString:#"$"];
// sanity checks
if (components.count < 2) return; // maybe no $ characters found
if (components.count % 2) return; // not an even number of $s
NSMutableString *out = [NSMutableString string];
for (int i=0; i< components.count; i++) {
[out appendString:components[i]];
[out appendString: (i % 2) ? #"]" : #"[" ];
}
// out = #"This is a [special markup] sentence."
Try this one
NSMutableString *string=[[NSMutableString alloc]initWithString:#"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];
NSMutableString *string=[[NSMutableString alloc]initWithString:#"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];
BOOL open=YES;
for (NSUInteger i=0; i<[string length];i++) {
if ([string characterAtIndex:i]=='$') {
if (open) {
[string replaceCharactersInRange:NSMakeRange(i, 1) withString:#"["];
open=!open;
}
else{
[string replaceCharactersInRange:NSMakeRange(i, 1) withString:#"]"];
open=!open;
}
}
}
NSLog(#"-->%#",string);
Output:
-->This is a message with [specially formatted] content. This is a message with [specially formatted] content

parsing string starting with # and # in objective-C

So I am trying to parse a string that has the following format:
baz#marroon#red#blue #big#cat#dog
or, it can also be separated by spaces:
baz #marroon #red #blue #big #cat #dog
and here's how I am doing it now:
- (void) parseTagsInComment:(NSString *) comment
{
if ([comment length] > 0){
NSArray * stringArray = [comment componentsSeparatedByString:#" "];
for (NSString * word in stringArray){
}
}
}
I've got the components separated by space working, but what if it has no space.. how do I iterate through these words? I was thinking of using regex.. but I have no idea on how to write such regex in objective-C. Any idea, for a regex that would cover both of these cases?
Here's my first attempt:
NSError * error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(#|#)\\S+" options:NSRegularExpressionCaseInsensitive error:&error];
NSArray* wordArray = [regex matchesInString:comment
options:0 range:NSMakeRange(0, [comment length])];
for (NSString * word in wordArray){
}
Which doesn't work.. I think my regex is wrong.
Here is a way to do it using NSScanner that puts the separated strings and a string representation of their ranges into an array (this assumes that your original string started with a # -- if it doesn't and you need it to, then just prepend the hash to the string at the start).
NSMutableArray *array = [NSMutableArray array];
NSString *str = #"#baz#marroon#red#blue #big#cat#dog";
NSScanner *scanner = [NSScanner scannerWithString:str];
NSCharacterSet *searchSet = [NSCharacterSet characterSetWithCharactersInString:#"##"];
NSString *outputString;
while (![scanner isAtEnd]) {
[scanner scanUpToCharactersFromSet:searchSet intoString:nil];
[scanner scanCharactersFromSet:searchSet intoString:&outputString];
NSString *symbol = [outputString copy];
[scanner scanUpToCharactersFromSet:searchSet intoString:&outputString];
NSString *wholePiece = [[symbol stringByAppendingString:outputString]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *rangeString = NSStringFromRange([str rangeOfString:wholePiece]);
[array addObject:wholePiece];
[array addObject:rangeString];
}
NSLog(#"%#",array);
I think the regular expression you really want is [##]?\\w+. It will find groups of letters optionally preceded by an # or #. Your expression wouldn't work because it looks for any non-space character, which includes # and #. (Depending on what can be in the "words," you might want something more or less specific than \w, but it isn't clear from the question.)
If you need the ranges, then NSRegularExpression probably works well:
NSString *comment = #"#baz#marroon#red#blue #big#cat#dog";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[##]\\w+" options:0 error:nil];
NSArray* wordArray = [regex matchesInString:comment
options:0
range:NSMakeRange(0, [comment length])];
for (NSTextCheckingResult *result in wordArray)
NSLog(#"%#", [comment substringWithRange:result.range]);
Or, [##][a-zA-z]+ works if you're ok with ASCII alpha words only.

NSString to NSArray

I want to split an NSString into an NSArray. For example, given:
NSString *myString=#"ABCDEF";
I want an NSArray like:
NSArray *myArray={A,B,C,D,E,F};
How to do this with Objective-C and Cocoa?
NSMutableArray *letterArray = [NSMutableArray array];
NSString *letters = #"ABCDEF𝍱क्";
[letters enumerateSubstringsInRange:NSMakeRange(0, [letters length])
options:(NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[letterArray addObject:substring];
}];
for (NSString *i in letterArray){
NSLog(#"%#",i);
}
results in
A
B
C
D
E
F
𝍱
क्
enumerateSubstringsInRange:options:usingBlock: available for iOS 4+ can enumerate a string with different styles. One is called NSStringEnumerationByComposedCharacterSequences, what will enumerate letter by letter but is sensitive to surrogate pairs, base characters plus combining marks, Hangul jamo, and Indic consonant clusters, all referred as Composed Character
Note, that the accepted answer "swallows" 𝍱and breaks क् into क and ्.
Conversion
NSString * string = #"A B C D E F";
NSArray * array = [string componentsSeparatedByString:#" "];
//Notice that in this case I separated the objects by a space because that's the way they are separated in the string
Logging
NSLog(#"%#", array);
This is what the console returned
NSMutableArray *chars = [[NSMutableArray alloc] initWithCapacity:[theString length]];
for (int i=0; i < [theString length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%C", [theString characterAtIndex:i]];
[chars addObject:ichar];
}
This link contains examples to split a string into a array based on sub strings and also based on strings in a character set. I hope that post may help you.
here is the code snip
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[myString length]];
for (int i=0; i < [myString length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [myString characterAtIndex:i]];
[characters addObject:ichar];
}
Without loop you can use this:
NSString *myString = #"ABCDEF";
NSMutableString *tempStr =[[NSMutableString alloc] initWithString:myString];
if([myString length] != 0)
{
NSError *error = NULL;
// declare regular expression object
NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern:#"(.)" options:NSMatchingReportCompletion error:&error];
// replace each match with matches character + <space> e.g. 'A' with 'A '
[regex replaceMatchesInString:tempStr options:NSMatchingReportCompletion range:NSMakeRange(0,[myString length]) withTemplate:#"$0 "];
// trim last <space> character
[tempStr replaceCharactersInRange:NSMakeRange([tempStr length] - 1, 1) withString:#""];
// split into array
NSArray * arr = [tempStr componentsSeparatedByString:#" "];
// print
NSLog(#"%#",arr);
}
This solution append space in front of each character with the help of regular expression and uses componentsSeparatedByString with <space> to return an array
Swift 4.2:
String to Array
let list = "Karin, Carrie, David"
let listItems = list.components(separatedBy: ", ")
Output : ["Karin", "Carrie", "David"]
Array to String
let list = ["Karin", "Carrie", "David"]
let listStr = list.joined(separator: ", ")
Output : "Karin, Carrie, David"
In Swift, this becomes very simple.
Swift 3:
myString.characters.map { String($0) }
Swift 4:
myString.map { String($0) }

How to test a string for text

I would like to test a string to see if anywhere it contains the text "hello". I would like the test to not take into account capitalization. How can I test this string?
Use the below code as reference to find check for a substring into a string.
NSString* string = #"How to test a string for text" ;
NSString* substring = #"string for" ;
NSRange textRange;
textRange =[string rangeOfString:substring options:NSCaseInsensitiveSearch];
if(textRange.location != NSNotFound)
{
//Does contain the substring
}
-[NSString rangeOfString: options:] will do it.
NSRange range = [string rangeOfString:#"hello" options:NSCaseInsensitiveSearch];
BOOL notFound = range.location==NSNotFound;
I am assuming all words are separated by a space, and that there is no punctuation. If there is punctuation.
NSArray *dataArray = [inputString componentsSeparatedByString:#" "];
for(int i=0; i<[dataArray count]){
if([[dataArray objectAtIndex:i] isEqualToString:#"hello"]){
NSLog(#"hello has been found!!!");
}
}
I haven't tested this but it should work in theory.
Check out the docs for ways to remove punctuation and make the string all lower case. This should be pretty straight-forward.
Other solutions here are good but you should really use a regex,
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^(hello)*$"
options:NSRegularExpressionCaseInsensitive
error:&error];
Docs are here: http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html