how to match string portion with NSArray values in objective-c - objective-c

I have following array and search string.
NSArray *values =[NSArray arrayWithObjects:#"abc",#"xyz",#"cba",#"yzx",nil];
NSString *search = #"startcba";
I want to search string's end part within an array elements. My expected search result will be #"cba". Please let me know how to find the desire value in array for giving search.
Thanks,

You can use NSPredicate to get the elements that satisfy your requirement.
NSPredicate * predicate = [NSPredicate predicateWithFormat:#" %# ENDSWITH SELF ", search];
NSArray * searchResults = [values filteredArrayUsingPredicate:predicate];

The NSPredicates way is great.
Here is an approach with rangeOfString:
NSArray *values =[NSArray arrayWithObjects:#"abc",#"xyz",#"cba",#"yzx",nil];
NSString *search = #"startcba";
NSUInteger searchLength = [search length];
NSString *result = nil;
for (NSString *val in values)
{
NSUInteger valLength = [val length];
NSRange expectedRange = NSMakeRange(searchLength - valLength, valLength);
NSRange rng = [search rangeOfString:val];
if ( rng.location == expectedRange.location && rng.length == expectedRange.length )
{
result = val;
break;
}
}

Related

search NSArray with regex

I have an array of names. If any of the name is already there then on inserting new name I want to append the counter eg John (02) if John already present in array then John (03) if it is third entry of name John.
Is there any way to filter array with Regex so that I can filter all records with pattern "John (xx)"?
Yup. You have to loop through the array and check with regex. You have to do this, since if you just check if the array contains your string, it won't return true if you search for "John" and the only one in your array is "John1"
NSMutableArray *testArray = [[NSMutableArray alloc] initWithObjects:#"John", #"Steve", #"Alan", #"Brad", nil];
NSString *nameToAdd = #"John";
NSString *regex = [NSString stringWithFormat:#"%#[,]*[0-9]*", nameToAdd];
NSPredicate *myTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
for (int i = 0; i < [testArray count]; i++)
{
NSString *string = [testArray objectAtIndex:i];
if ([myTest evaluateWithObject:string])
{
// Matches
NSLog(#" match !");
int currentValue;
NSArray *split = [string componentsSeparatedByString:#","];
if ([split count] == 1)
{
// Set to 2
currentValue = 2;
}
else
{
currentValue = [[split objectAtIndex:1] intValue];
currentValue++;
}
NSString *newString = [NSString stringWithFormat:#"%#,%d", nameToAdd, currentValue];
[testArray replaceObjectAtIndex:i withObject:newString];
}
}
for (NSString *string in testArray)
{
NSLog(#"%#", string);
}
This will replace "John" with "John,2", and if you search for "John" a third time it will replace it with "John,3".
Hope this helps
You can create a predicate for your regular expression and then filter the array using the predicate. Based on the count of the matches, you can update the new value being added as needed.
NSMutableArray *currentNames = ... // the current list of names
NSString *newName = ... // the new name to add
NSString *regex = [NSString stringWithFormat:#"%# \\([0-9]*\\)", newName];
NSPredicate *filter = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
NSArray *matches = [currentNames filteredArrayUsingPredicate:filter];
if (matches.count) {
NSString *updatedName = [NSString stringWithFormat:#"%# (%02d)", newName, matches.count];
[currentNames addObject:updatedName];
} else {
[currentNames addObject:newName];
}
You can filer an array with NSPredicate. Not too familiar with regex, but the following seems okay:
NSArray *array = #[#"John (01)", #"John (02)", #"John XX"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF MATCHES 'John [(]\\\\d{2}[)]'"];
NSArray *result = [array filteredArrayUsingPredicate:predicate];
NSLog( #"%#", result ); // Output John (01), John (02)

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);

How to parse a string format like [***]***?

I need to parse a string like [abc]000, and what I want to get is an array containing abc and 000. Is there an easy way to do it?
I'm using code like this:
NSString *sampleString = #"[abc]000";
NSArray *sampleParts = [sampleString componentsSeparatedByString:#"]"];
NSString *firstPart = [[[sampleParts objectAtIndex:0] componentsSeparatedByString:#"["] lastObject];
NSString *lastPart = [sampleParts lastObject];
But it's inefficient and didn't check whether the string is in a format like [**]**.
For this simple pattern, can just parse yourself like:
NSString *s = #"[abc]000";
NSString *firstPart = nil;
NSString *lastPart = nil;
if ([s characterAtIndex: 0] == '[') {
NSUInteger i = [s rangeOfString:#"]"].location;
if (i != NSNotFound) {
firstPart = [s substringWithRange:NSMakeRange(1, i - 1)];
lastPart = [s substringFromIndex:i + 1];
}
}
Or you could learn to use the NSScanner class.
As always, there are lots of ways to do this.
OPTION 1
If these are fixed length strings (each part is always three characters) then you can simply get the substrings directly:
NSString *sampleString = #"[abc]000";
NSString *left = [sampleString substringWithRange:NSMakeRange(1, 3)];
NSString *right = [sampleString substringWithRange:NSMakeRange(5, 3)];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
OPTION 1 (shortened)
NSArray *parts = #[ [sampleString substringWithRange:NSMakeRange(1, 3)],
[sampleString substringWithRange:NSMakeRange(5, 3)] ];
NSLog(#"%#", parts);
OPTION 2
If they aren't always three characters, then you can use NSScanner:
NSString *sampleString = #"[abc]000";
NSScanner *scanner = [NSScanner scannerWithString:sampleString];
// Skip the first character if we know that it will always start with the '['.
// If we can not make this assumption, then we would scan for the bracket instead.
scanner.scanLocation = 1;
NSString *left, *right;
// Save the characters until the right bracket into a string which we store in left.
[scanner scanUpToString:#"]" intoString:&left];
// Skip the right bracket
scanner.scanLocation++;
// Scan to the end (You can use any string for the scanUpToString that doesn't actually exist...
[scanner scanUpToString:#"\0" intoString:&right];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
RESULTS (for all options)
2013-05-10 00:25:02.031 Testing App[41906:11f03] (
abc,
000
)
NOTE
All of these assume well-formed strings, so you should include your own error checking.
try like this ,
NSString *sampleString = #"[abc]000";
NSString *pNRegex = #"\\[[a-z]{3}\\][0-9]{3}";
NSPredicate *PNTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pNRegex];
BOOL check=[PNTest evaluateWithObject:sampleString ];
NSLog(#"success:%i",check);
if success comes as 1 then you can perform the action for separating string into array.

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
)

find number of NSArray object on string

I would like to count my NSArray object of my NSString. My NSArray has #"a", #"w" objects, and my string is #"abcdefgw". I would like to know how many times the #"w" object is there in my string.
You can use - (NSArray *)componentsSeparatedByString:(NSString *)separator, though this may have boundary issues. You can also use stringByReplacingOccurrencesOfString:withString: like this:
NSString *shortString = [myString stringByReplacingOccurrencesOfString:#"w" withString:#""];
return mystring.length-shortString.length;
if you are looking to count substrings you will have to search for substrings then shrink the range each time... something like.
-(NSInteger)occurrencesOfSubstring:(NSString *)substring inString:(NSString *)string
{
int occurrences =0;
NSRange searchRange = NSMakeRange(0, [string length]);
NSRange foundRange;
do {
foundRange = [string rangeOfString:substring options:NSCaseInsensitiveSearch range:searchRange];
if ((foundRange.location != NSNotFound)) {
occurrences++;
searchRange.location = foundRange.location+foundRange.length;
searchRange.length = [string length] - (foundRange.location+foundRange.length);
}
}while (foundRange.location != NSNotFound);
return occurrences;
}