How to get count of elements that do have string value one - ios

How to get the count of elements present in array that contains only string #"one".
NSMutableArray *array = [[NSMutableArray alloc]initWithObject:#"one",#"one",#"two",#"one",#"five",#"one",nil];
How to get the count of array which contains one in it.

There is another solution from the ones mentioned
// Query to find elements which match 'one'
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains %#",
#"one"];
// Use the above predicate on your array
// The result will be a `NSArray` so from there we count the elements on this array
NSInteger count = [array filteredArrayUsingPredicate:predicate].count;
// Prints out number of elements
NSLog(#"%li", (long)count);

Many ways to go:
NSMutableArray *array = [[NSMutableArray alloc]initWithObject:#"one",#"one",#"two",#"one",#"five",#"one",nil];
Use blocks:
NSInteger occurrenceCount = [[array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {return [obj isEqual:#"one"];}] count];
Use loop:
int occurrenceCount = 0;
for(NSString *str in array){
occurrenceCount += ([string isEqualToString:#"one"]?1:0);
}
Use NSCountedSet:
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
NSLog(#"Occurrences of one: %u", [countedSet countForObject:#"one"]);
Use NSPredicate:(as EridB suggested)
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains %#",
#"one"];
NSInteger occurrenceCount = [array filteredArrayUsingPredicate:predicate].count;
Check answers here for more detail.

NSArray *array = #[#"one",#"one",#"two",#"one",#"five",#"one"];
NSPredicate *searchCountString= [NSPredicate predicateWithFormat:#"SELF contains %#",#"one"];
NSInteger count = [array filteredArrayUsingPredicate:searchCountString].count;
NSLog(#"%ld",(long)count);

Related

How get objects from one array with same properties of other?

For example:
I have two NSMutableArray. One #[1,2,3,4,5,6,7]. Other have objects like
#[
#{#idObjectToSearch":1, #"name":#"aaaaa", #"surname": #"bbbbb"}, #{#idObjectToSearch":2, #"name":#"aaaaa", #"surname": #"ccccc"},
...
#{#idObjectToSearch":100, #"name":#"aaaaa", #"surname": #"cccdcd"}
];
So how I could extract needed objects from second array more effective way?
You need to use NSPredicate with your second array.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"idObjectToSearch IN %#", firstArray];
//In above predicate instead of passing `1` you need to pass object from first array that you want.
NSArray *filterArray = [secondArray filteredArrayUsingPredicate:predicate];
//Now access Array objects
if (filterArray.count > 0) {
NSLog(#"%#",filterArray);
}
You can do it like this
NSMutableArray * arrSorted = [NSMutableArray new];
for(int i=0;i<arr.count;i++) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"idObjectToSearch == %#", firstArray[i]];
NSUInteger index = [secondArray indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [predicate evaluateWithObject:obj];
}];
if (index != NSNotFound) {
[arrSorted addObject:[arrM objectAtIndex:index]];
}
}
arrSorted will contain your sorted data

String contains any element of an Array [duplicate]

I know I can check if a string contains another string like this
NSString *string = #"hello bla bla";
if ([string rangeOfString:#"bla"].location == NSNotFound) {
NSLog(#"string does not contain bla");
} else {
NSLog(#"string contains bla!");
}
But what if I have an NSArray *arary = #[#"one",#"two", #"three", #"four"] and I wanted to check if a string contains either one of these without just loop or have a bunch of or's (|| ). So it would be something like this
if (array contains one or two or three or four) {
//do something
}
But if I have a longer array this becomes tedious so is there another way, without just looping through?
EDIT
I want to check if myArray has any of theses values in valuesArray
valuesArray =#[#"one",#"two", #"three", #"four"];
myArray = [#"I have one head", #"I have two feet", #"I have five fingers"]
OUTPUT
outputArray = #[#"I have one head", #"I have two feet"]
There you go:
NSArray* arrRet = [myArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id __nonnull evaluatedObject, NSDictionary<NSString *,id> * __nullable bindings) {
for(NSString* val in valuesArray) {
if ([evaluatedObject rangeOfString:val].location != NSNotFound)
return true;
}
return false;
}]];
arrRet contains exactly the two desired strings.
A little bit more magic later you have your code without writing a loop :P
NSArray* arrRet = [myArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<NSString *,id> * bindings) {
BOOL __block match = false;
[valuesArray enumerateObjectsUsingBlock:^(id __nonnull obj, NSUInteger idx, BOOL * __nonnull stop) {
*stop = match = [evaluatedObject rangeOfString:obj].location != NSNotFound;
}];
return match;
}]];
You could use a NSCompoundPredicate
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
Where your subPredicates must look like
(
SELF CONTAINS[c] "one",
SELF CONTAINS[c] "two",
SELF CONTAINS[c] "three",
SELF CONTAINS[c] "four"
)
To get there from
NSArray *array = #[#"one", #"two", #"three", #"four"]
You could use a for loop, but as you are opposed to that, let's cheat:
by using a category I each NSArray functional mapping, but instead of looping, I use enumerating
#interface NSArray (Map)
-(NSArray *) vs_map:(id(^)(id obj))mapper;
#end
#implementation NSArray (Map)
-(NSArray *)vs_map:(id (^)(id))mapper
{
NSMutableArray *mArray = [#[] mutableCopy];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id mapped = mapper(obj);
[mArray addObject:mapped];
}];
return [mArray copy];
}
#end
Now I can create the subPredicates like
NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
return [NSPredicate predicateWithFormat:#"SELF contains[c] %#", obj];
}];
and create the compound predicate like
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
and use it
BOOL doesContain = [predicate evaluateWithObject:string];
et voilĂ : No (obvious) looping, while there is one hidden in the enumeration and probably in the predicate as-well.
Now with the changed question you basically ask for filtering. You can use the same predicate for that:
NSArray *testarray = #[#"I have one head", #"I have two feet", #"I have five fingers"];
NSArray *arary = #[#"one",#"two", #"three", #"four"];
NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
return [NSPredicate predicateWithFormat:#"SELF contains[c] %#", obj];
}];
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
NSArray *results = [testarray filteredArrayUsingPredicate:predicate];
results now contains
(
I have one head,
I have two feet
)
the complete code
#import <Foundation/Foundation.h>
#interface NSArray (Map)
-(NSArray *) vs_map:(id(^)(id obj))mapper;
#end
#implementation NSArray (Map)
-(NSArray *)vs_map:(id (^)(id))mapper
{
NSMutableArray *mArray = [#[] mutableCopy];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id mapped = mapper(obj);
[mArray addObject:mapped];
}];
return [mArray copy];
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSArray *testarray = #[#"I have one head", #"I have two feet", #"I have five fingers"];
NSArray *arary = #[#"one",#"two", #"three", #"four"];
NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
return [NSPredicate predicateWithFormat:#"SELF contains[c] %#", obj];
}];
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
NSArray *results = [testarray filteredArrayUsingPredicate:predicate];
}
return 0;
}
Besides my cheating the my other question, here an idea how really to avoid time costly looping: Use Set computation magic!
created a class 'Sentence', instantiate it with the strings to test
created a 'Word' class that takes a word to search for
overwrite both classes' isEqual: method to match for if a word is in the sentence (use sets there too!)
put those into an array.
from this array create a NS(*)Set object
put all word in a set
execute union on it.

Filter NSMutableArray on the base of filtering another NSMutableArray

I have 3 NSMutableArrays of identical size. They are "linked" that means that for the corresponding index they have something related to each other.
tableData = [NSMutableArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", nil]
thumbnails = [NSMutableArray arrayWithObjects:#"egg_benedict.jpg", #"mushroom_risotto.jpg", #"full_breakfast.jpg",nil]
prepTime = [NSMutableArray arrayWithObjects:#"10min", #"15min", #"8min",nil]
This comes from a tutorial I'm playing on.
I'm filtering the tableData array like this:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResultsData = [[tableData filteredArrayUsingPredicate:resultPredicate] mutableCopy];
where searchText is the string containing the filter (for example "egg").
This works great, I mean I have the correct filtering. (searchResultsData is another NSMutableArray)
What I need to do is filter the other two NSMutableArrays on the basis of the result got from the NSPredicate above.
So I created other two NSMutableArrays called "searchResultThumbnails" and "searchResultPrepTime".
I'm expecting this: if I filter using the word "egg" I want the first element containing "egg" from the "tableData" array (in this case only one element) and the correspondent element at index in the thumbnails and preptime arrays.
So after filtering with "Egg" the result should be:
searchResultData = "Egg"
searchResultThumbnails = "egg_benedict.jpg"
searchResultPrepTime = "10min"
Thank you for your help.
Believing "They are "linked" that means that for the corresponding index they have something related to each other." as your situation
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResultsData = [[tableData filteredArrayUsingPredicate:resultPredicate] mutableCopy];
NSString *searchedText = [searchResultsData objectAtIndex:0];
NSInteger index = [tableData indexOfObject:searchedText]; //if searchedText = "Egg"
NSString *thumb = [thumbnails objectAtIndex:index];
NSString *prep= [prepTime objectAtIndex:index];
But this is not a better way to do this.
You got couple of options like
You can use a custom Class which might have properties item, thumbnail, prepTime.
You can also use a Array of dictionaries similar to the following format,
array = (
{
searchResultData = "Egg"
searchResultThumbnails = "egg_benedict.jpg"
searchResultPrepTime = "10min"
}
{
searchResultData = "someItem"
searchResultThumbnails = "some.jpg"
searchResultPrepTime = "10min"
}
)
Try this:
NSArray* tableData = [NSMutableArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", nil];
NSArray* thumbnails = [NSMutableArray arrayWithObjects:#"egg_benedict.jpg", #"mushroom_risotto.jpg", #"full_breakfast.jpg",nil];
NSArray* prepTime = [NSMutableArray arrayWithObjects:#"10min", #"15min", #"8min",nil];
NSMutableArray *storedIndex = [NSMutableArray arrayWithCapacity:tableData.count];
for (NSUInteger i = 0 ; i != tableData.count ; i++) {
[storedIndex addObject:[NSNumber numberWithInteger:i]];
}
//Now you are going to sort tabledata.. with it we will sort storedIndexs
//suppose we will compare the strings for this time
[storedIndex sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
NSString *lhs = [[tableData objectAtIndex:[obj1 intValue]] lowercaseString];
NSString *rhs = [[tableData objectAtIndex:[obj2 intValue]] lowercaseString];
return [lhs compare:rhs];
}]; //now storedIndex are sorted according to sorted tableData array
NSMutableArray *sortedTableData = [NSMutableArray arrayWithCapacity:tableData.count];
NSMutableArray *sortedThumbnail = [NSMutableArray arrayWithCapacity:tableData.count];
NSMutableArray *sortedPrepTime = [NSMutableArray arrayWithCapacity:tableData.count];
[p enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSUInteger pos = [obj intValue];
[sortedTableData addObject:[tableData objectAtIndex:pos]];
[sortedThumbnail addObject:[thumbnails objectAtIndex:pos]];
[sortedPrepTime addObject:[prepTime objectAtIndex:pos]];
}];
//Now all will be correct index relation to each other as previous
It will work perfectly.
Happy coding. :)

Filter array by first letter of string property

I have an NSArray with objects that have a name property.
I would like filter the array by name
NSString *alphabet = [agencyIndex objectAtIndex:indexPath.section];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSMutableArray *listSimpl = [[NSMutableArray alloc] init];
for (int i=0; i<[[Database sharedDatabase].agents count]; i++) {
Town *_town = [[Database sharedDatabase].agents objectAtIndex:i];
[listSimpl addObject:_town];
}
NSArray *states = [listSimpl filteredArrayUsingPredicate:predicate];
But I get an error - "Can't do a substring operation with something that isn't a string (lhs = <1, Arrow> rhs = A)"
How can I do this? I would like to filter the array for the first letter in name being 'A'.
Try with following code
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF like %#", yourName];
NSArray *filteredArr = [yourArray filteredArrayUsingPredicate:pred];
EDITED :
NSPredicate pattern should be:
NSPredicate *pred =[NSPredicate predicateWithFormat:#"name beginswith[c] %#", alphabet];
Here is one of the basic use of NSPredicate for filtering array .
NSMutableArray *array =
[NSMutableArray arrayWithObjects:#"Nick", #"Ben", #"Adam", #"Melissa", #"arbind", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"];
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
NSArray offers another selector for sorting arrays:
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(Person *first, Person *second) {
return [first.name compare:second.name];
}];
If you want to filter array take a look on this code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"qwe"];
NSArray *result = [self.categoryItems filteredArrayUsingPredicate:predicate];
But if you want to sort array take a look on the following functions:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context hint:(NSData *)hint;
- (NSArray *)sortedArrayUsingSelector:(SEL)comparator;
visit https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html
use this
[listArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Checkout this library
https://github.com/BadChoice/Collection
It comes with lots of easy array functions to never write a loop again
So you can just do
NSArray* result = [thArray filter:^BOOL(NSString *text) {
return [[name substr:0] isEqualToString:#"A"];
}] sort];
This gets only the texts that start with A sorted alphabetically
If you are doing it with objects:
NSArray* result = [thArray filter:^BOOL(AnObject *object) {
return [[object.name substr:0] isEqualToString:#"A"];
}] sort:#"name"];

Removing negative numbers from NSArray in Objective C

I am new to Objective C. In my application, I am having array of data, in which I need only positive numbers and need to delete negative numbers.
result = [NSMutableArray arrayWithObjects: #"1",#"2",#"3","-4","-5","6","9",nil];
NSLog(#" Before Remove %d", [result count]);
NSString *nullStr = #"-";
[result removeObject:nullStr];
How to achieve this? Any pointers?
You can use a predicate to filter the array
NSArray * numbers = #[#"1", #"2", #"3", #"-4", #"-5", #"6", #"9"];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"integerValue >= 0"];
NSArray * positiveNumbers = [numbers filteredArrayUsingPredicate:predicate];
Result
[#"1", #"2", #"6", #"9"]
Also note that this will work with both an array of NSNumbers and an array of NSStrings, since they both feature the integerValue method.
the one you wrote is an array of strings, if that's ok you can loop the array and remove strings that starts with - using
Since you cannot remove objects while iterating, you can create a new array and store only positive numbers (or mark item to be deleted and delete after the loop)
NSMutableArray onlyPositives = [[NSMutableArray alloc] init]
for(int i=0; i < [result count]; i++)
{
if(![result[i] hasPrefix:#"-"])
[onlyPositives add:[result[i]]
}
Try This:
for(NSString *number in [result copy])
{
if([number intValue] < 0)
{
[result removeObject:number];
}
}
If you have an array and you want to filter items out of it, then using an NSPredicate is a good way to do it.
You haven't said whether your array contains NSNumbers or NSStrings, so here's a demonstration of how to use predicates to filter an array in both cases
// Setup test arrays
NSArray *stringArray = #[#"-1", #"0", #"1", #"2", #"-3", #"15"];
NSArray *numberArray = #[#(-1), #0, #1, #2, #(-3), #15];
// Create the predicates
NSPredicate *stringPredicate = [NSPredicate predicateWithFormat:#"integerValue >= 0"];
NSPredicate *numberPredicate = [NSPredicate predicateWithFormat:#"SELF >= 0"];
// Filtering the original array returns a new filtered array
NSArray *filteredStringArray = [stringArray filteredArrayUsingPredicate:stringPredicate];
NSArray *filteredNumberArray = [numberArray filteredArrayUsingPredicate:numberPredicate];
// Just to see the results, lets log the filtered arrays.
NSLog(#"New strings %#", filteredStringArray); // 0, 1, 2, 15
NSLog(#"New strings %#", filteredNumberArray); // 0, 1, 2, 15
This should get you started.
NSIndexSet *indexesOfNegativeNumbers = [result indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [(NSString *)obj hasPrefix:#"-"];
}];
[result removeObjectsAtIndexes:indexesOfNegativeNumbers];

Resources