Removing negative numbers from NSArray in Objective C - ios

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

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

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

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

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. :)

NSPredicate filtering an array of arrays using another array

I want to filter an array of arrays using another array which is a subset of these arrays.
NSMutableArray* y = [NSMutableArray arrayWithObjects:#"A",#"B", nil];
NSArray *array = #[
#[#"A", #"B", #"C"],
#[#"A", #"B", #"E"],
#[#"A", #"B", #"D"],
#[#"B", #"C", #"D"],
];
I want to filter the second array such that it contains the items which has both "A" and "B" in it.
I used the predicate:
NSPredicate *intersectPredicate =[NSPredicate predicateWithFormat:#"ANY SELF IN %#", y];
NSArray *intersect = [array filteredArrayUsingPredicate:intersectPredicate];
But this gives me all the items in second Array. I think ANY/SOME is considering (A || B) I want to have (A && B). I tried ALL but it gives nothing.
Any/Some would give all the arrays which contain either A or B.
All would give all the arrays which have just 2 elements A & B.
By defining a custom predicate we can get the desired results:
NSPredicate *intersectPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
for (NSString *str in y) {
if (![evaluatedObject containsObject:str]) {
return false;
}
}
return true;
}];
NSArray *intersect = [array filteredArrayUsingPredicate:intersectPredicate];

How to properly filter a NSArray using a NSPredicate

I am trying to find the tags inside a NSDictionary inside myAr that matches the criteria of str and I want the result that has only those exact arrays no more nor less. In this example I want only the 2nd NSDictionary of myAr.
I though of trying to achieve this by using a predicate but that always returns empty when i use arrays.
I am trying to filter using an array but this is not working. I was wondering if anyone could tell me what i am doing wrong and how could i achieve my objective. thanks in advance
NSArray * myAr = #[ #{ #"tags": #[#"one",#"two",#"three"],
#"number": #"4"
},
#{ #"tags": #[#"one",#"two"],
#"number":#"4"
},
#{ #"tags": #[#"one",#"two",#"four"],
#"number":#"4"
},
#{ #"tags": #[#"chacho",#"chocho"],
#"number":#"4"
},
#{ #"tags": #[#"one"],
#"number":#"4"
} ];
NSArray* str = #[#"one",#"two"];
NSPredicate* pre = [NSPredicate predicateWithFormat:#"tags CONTAINS %# ",str];
myAr = [myAr filteredArrayUsingPredicate:pre];
NSLog(#"%#",myAr);
If I understand your question correctly, you just have to replace "CONTAINS" by "="
in the predicate:
[NSPredicate predicateWithFormat:#"tags = %# ",str]
This gives an array with all dictionaries where the "tags" value is equal to the
given array str. In your example, it returns an array with the second dictionary
only.
UPDATE: To find all dictionaries where the "tags" value is an array with the
given elements, but independent of the order, the following slightly more
complicated predicate should work:
[NSPredicate predicateWithFormat:#"tags.#count = %d AND SUBQUERY(tags, $t, $t in %#).#count = %d",
[str count], str, [str count]];
UPDATE 2: That was too complicated, the following predicate seems to work as well:
[NSPredicate predicateWithFormat:#"tags.#count = %d AND ALL tags in %#",
[str count], str]
(I have assumed that str contains only different elements.)
For an answer that uses neither a for loop nor predicate format strings, try using a block and make use of NSSet to determine if the set of tags you want to match is equal to a set of the array element's tags. For example:
NSSet* desiredTags = [NSSet setWithObjects:#"one", #"two", nil];
NSPredicate *tagFilterPredicate = [NSPredicate
predicateWithBlock:^BOOL (id data, NSDictionary *bindings) {
NSSet *tags = [NSSet setWithArray:[data objectForKey:#"tags"]];
return [desiredTags isEqual:tags];
}];
NSArray *resultArray = [myArr filteredArrayUsingPredicate:tagFilterPredicate];
Bear in mind that this does allocate a set per iteration. So, if you're looking to avoid allocations, this is not adequate. Otherwise, it at least avoids a format string.
A brute-force way to do this would be to remove your predicate and just enumerate:
NSArray *required = #[#"one", #"two"];
NSMutableArray *matches = [#[] mutableCopy];
[myAr enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSArray class]]) {
BOOL match = YES;
for (NSString *item in required) {
if (![obj containsObject:item]) {
match = NO;
break;
}
}
if (match && [(NSArray *)obj count] == required.count) {
[matches addObject:obj];
}
}
}];
}];

Resources