Given is an NSArray with objects, each of which has an NSArray with floats, stored as NSNumbers.
I am trying to create an NSPredicate to filter my main array based on the float values. So, for instance, how to get all objects that have the value 234.6 +/- 0.8 as one of the floats in the sub-array?
I can do something like this for a one-dimensional NSArray of floats:
float targetFloat = 234.6;
float delta = 0.8;
filterPredicate = [NSPredicate predicateWithFormat: #"myFloat > %f AND myFloat < %f", (targetFloat - delta), (targetFloat + delta)];
filteredArray = [originalArray filteredArrayUsingPredicate: filterPredicate];
But how do I change it for my 2D NSArray with NSNumbers?
You can use "SELF[index]" in a predicate to access specific elements of the sub-array.
The following predicate finds all sub-arrays where the first element is in the
specified range:
float lowValue = 1.5;
float hiValue = 2.5;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF[0] > %f AND SELF[0] < %f", lowValue, hiValue];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
If you want to find the sub-arrays that contain any number in the specified range, use
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF BETWEEN %#", #[#(lowValue), #(hiValue)]];
Your predicate can access the object's property that holds the array by name; I've called this list in the example below. Then use the ANY keyword to check all the values in the array, and BETWEEN to find out if those values are within your chosen range.
#import <Foundation/Foundation.h>
#interface Grumolo : NSObject
#property (copy, nonatomic) NSArray * list;
#end
#implementation Grumolo
- (NSString *)description
{
return [NSString stringWithFormat:#"%#: %p, list: %#", NSStringFromClass([self class]), self, [self list]];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
float target = 234;
float delta = 0.8;
NSPredicate * p = [NSPredicate predicateWithFormat:#"ANY list BETWEEN %#", #[#(target-delta), #(target+delta)]];
NSArray * yes = #[#234, #10, #100];
NSArray * yes2 = #[#0, #16, #234];
NSArray * no = #[#1, #2, #3];
Grumolo * g1 = [Grumolo new];
[g1 setList:yes];
Grumolo * g2 = [Grumolo new];
[g2 setList:yes2];
Grumolo * g3 = [Grumolo new];
[g3 setList:no];
NSLog(#"%#", [#[g1, g2, g3] filteredArrayUsingPredicate:p]);
}
return 0;
}
You might also like to try predicateWithBlock:, which would let you express what you're trying to do with a traditional loop over each array, returning YES if you find an element that meets your criteria and NO if you exhaust the list.
NSPredicate * pb = [NSPredicate predicateWithBlock:^BOOL(Grumolo * evaluatedObject, NSDictionary *bindings) {
NSArray * list = [evaluatedObject list];
__block BOOL result = NO;
[list enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
BOOL moreThanLower = (NSOrderedDescending == [obj compare:#(target-delta)]);
BOOL lessThanUpper = (NSOrderedAscending == [obj compare:#(target+delta)]);
if( moreThanLower && lessThanUpper ){
*stop = YES;
result = YES;
return;
}
}];
return result;
}];
Related
I have one array with data A=[a,b,c] and another with data B=[d,e,f]. I need to perform this type of operation a.d+ b.e+c.f (Note=Here (.) denotes multplication)and get the result. How can i do that using Objective-C?
Thanks in advance.
Define the function that does the multiplication and addition like this:
- (double)multiply:(NSArray <NSNumber *> *)vector1 withVector:(NSArray <NSNumber *> *)vector2 {
NSAssert(vector1.count == vector2.count, #"Both arrays should contain the same number of elements");
__block double result = 0;
[vector1 enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
double first = obj.doubleValue;
double second = vector2[idx].doubleValue;
result += first * second;
}];
return result;
}
This uses a block enumeration method on NSArray which gives me in index and a value, which I can use to get the value at the same index in the second array. Note also that I am using a typed array, so I don't have to cast the values to NSNumbers when using them.
Now you can just use the function:
NSArray *a = #[#1, #2, #3];
NSArray *b = #[#4, #5, #6];
NSArray *c = #[#1, #1, #1];
double res1 = [self multiply:a withVector:b]; // => 32.000000
double res2 = [self multiply:b withVector:c]; // => 15.000000
double res3 = [self multiply:c withVector:a]; // => 6.000000
NSNumber *myNum1 = [NSNumber numberWithInt:1];
NSNumber *myNum2 = [NSNumber numberWithInt:2];
NSNumber *myNum3 = [NSNumber numberWithInt:3];
NSArray *a = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
NSArray *b = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
int sum=0;
for (int i=0; i<[a count]; i++) {
NSLog(#"%#", (NSNumber*)[a objectAtIndex:i]);
sum =sum +[(NSNumber*)[a objectAtIndex:i] intValue]*[(NSNumber*)[b objectAtIndex:i] intValue];
}
NSLog(#"Sum is %d", sum);
Hope this helps
I'm unsure how to write this NSPredicate to achieve the following. I have an array of prefixes, and I want to know if any of them (plus an underscore) are the prefix of a given string. I don't need to know which matched, just a yes/no if any matched at all.
I can't seem to work this out, at the moment I have this
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
NSArray *bins = #[#"aaa", #"bbb", #"ccc"];
NSString* item = #"aaa_blah";
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%# BEGINSWITH SELF", item];
NSLog(#"%#", [[bins filteredArrayUsingPredicate:pred] count] ? #"YES" : #"NO");
}
}
The only way I could think of doing it was filtering the array - so firstly is there a better approach?
And secondly, I want it to return true only if the prefix is followed by an underscore so
#[#"aaa", #"bbb", #"ccc"];
#"aaa_blah"; // YES
#"aaablah"; // NO
#"bbbblah"; // NO
I'm not sure how to do that?
+(void)checkIfExists:(NSArray *)prefixes inMyobjects:(NSArray *)myObjects withDivider:(NSString *)divider
{
divider = #"_";
prefixes = #[#"aaa",#"bbb",#"ccc"];
myObjects = #[#"aaa_sd",#"dsf_ds",#"aaa_sss",#"aaabbb"];
NSMutableArray * resultsOfPredicate = [NSMutableArray new];
for (NSString * pre in prefixes)
{
NSString * iAmLookingFor = [NSString stringWithFormat:#"%#%#", pre, divider];
NSPredicate *prefixPredicate = [NSPredicate predicateWithFormat:#"SELF beginsWith[c] %#", iAmLookingFor];
NSArray * resultOfSearch = [myObjects copy];
resultOfSearch = [resultOfSearch filteredArrayUsingPredicate:prefixPredicate];
NSLog(#"ros %#",resultOfSearch);
[resultsOfPredicate addObject:#([resultOfSearch count])];
}
for (int i = 0; i<[resultsOfPredicate count]; i++)
{
NSLog(#"prefix %# isAppeared:%d",[prefixes objectAtIndex:i], [[resultsOfPredicate objectAtIndex:i] boolValue]);
}
}
I hope this will help.
I have an array of car and I am filtering it based on objects containing the letter i.
NSMutableArray *cars = [NSMutableArray arrayWithObjects:#"Maruthi",#"Hyundai", #"Ford", #"Benz", #"BMW",#"Toyota",nil];
NSString *stringToSearch = #"i";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",stringToSearch]; // if you need case sensitive search avoid '[c]' in the predicate
NSArray *results = [cars filteredArrayUsingPredicate:predicate];
results contains Maruthi,Hyundai. Instead of the elements, I want results to contain the indexes of the elements i.e 0,1.
NSMutableArray *cars = [NSMutableArray arrayWithObjects:#"Maruthi",#"BMW", #"Ford", #"Benz", #"Hyundai",#"Toyota",nil];
NSMutableArray * results = [[NSMutableArray alloc]init];
for(int i = 0;i<cars.count;i++)
{
NSString * obj = [cars objectAtIndex:i];
if([obj rangeOfString:#"i"].location == NSNotFound)
{
NSLog(#"Not Found");
}
else
{
int index = [cars indexOfObject:obj];
[results addObject:[NSNumber numberWithInt:index]];
}
}
Why not use
- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
Or similar?
Depending on your search criteria, something like this perhaps?
NSArray *array = #[#"Maruthi",#"Hyundai", #"Ford", #"Benz", #"BMW", #"Toyota"];
NSString *stringToSearch = #"i";
NSIndexSet *set = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
NSString *string = obj;
if (([string rangeOfString:stringToSearch].location == NSNotFound))
{
return NO;
}
return YES;
}];
The data structure that I want to question. Data is a Transformable field which in turn is a NSDictionary.
Obj = { //...
NSDictionary *data:#{
likesPeople:#[#{#"username":#"jack",#"id":#"ae3132"}]
}
}
what I want to do is search inside the NSArray *fetchResult to check that there is noone in likesPeople with X id .
My attempts on doing this always end up crashing highlighting that there is a problem in my NSPredicate declaration.
What am I doing wrong and How could I effectively fetch the information that I want?
SocialWall *theSocialWall = fetchResult[0];
NSLog(#"%#",theSocialWall.data);
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"data.likesPeople CONTAINS(c) %#",myUser.userWebID];
NSArray * result = [fetchResult filteredArrayUsingPredicate:predicate];
NSLog(#"%#",result);
not Contains(c) but Contains[c]
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
NSDictionary *d = #{#"key":#"hi my name dominik pich"};
NSArray *a = #[d];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"key CONTAINS[c] %#",#"dominik"];
NSArray * result = [a filteredArrayUsingPredicate:predicate];
NSLog(#"%#",result);
}
}
I'm trying to re-arrange words into alphabetical order. For example, tomato would become amoott, or stack would become ackst.
I've found some methods to do this in C with char arrays, but I'm having issues getting that to work within the confines of the NSString object.
Is there an easier way to do it within the NSString object itself?
You could store each of the string's characters into an NSArray of NSNumber objects and then sort that. Seems a bit expensive, so I would perhaps just use qsort() instead.
Here it's provided as an Objective-C category (untested):
NSString+SortExtension.h:
#import <Foundation/Foundation.h>
#interface NSString (SortExtension)
- (NSString *)sorted;
#end
NSString+SortExtension.m:
#import "NSString+SortExtension.h"
#implementation NSString (SortExtension)
- (NSString *)sorted
{
// init
NSUInteger length = [self length];
unichar *chars = (unichar *)malloc(sizeof(unichar) * length);
// extract
[self getCharacters:chars range:NSMakeRange(0, length)];
// sort (for western alphabets only)
qsort_b(chars, length, sizeof(unichar), ^(const void *l, const void *r) {
unichar left = *(unichar *)l;
unichar right = *(unichar *)r;
return (int)(left - right);
});
// recreate
NSString *sorted = [NSString stringWithCharacters:chars length:length];
// clean-up
free(chars);
return sorted;
}
#end
I think separate the string to an array of string(each string in the array contains only one char from the original string). Then sort the array will be OK. This is not efficient but is enough when the string is not very long. I've tested the code.
NSString *str = #"stack";
NSMutableArray *charArray = [NSMutableArray arrayWithCapacity:str.length];
for (int i=0; i<str.length; ++i) {
NSString *charStr = [str substringWithRange:NSMakeRange(i, 1)];
[charArray addObject:charStr];
}
NSString *sortedStr = [[charArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] componentsJoinedByString:#""];
// --------- Function To Make an Array from String
NSArray *makeArrayFromString(NSString *my_string) {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < my_string.length; i ++) {
[array addObject:[NSString stringWithFormat:#"%c", [my_string characterAtIndex:i]]];
}
return array;
}
// --------- Function To Sort Array
NSArray *sortArrayAlphabetically(NSArray *my_array) {
my_array= [my_array sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
return my_array;
}
// --------- Function Combine Array To Single String
NSString *combineArrayIntoString(NSArray *my_array) {
NSString * combinedString = [[my_array valueForKey:#"description"] componentsJoinedByString:#""];
return combinedString;
}
// Now you can call the functions as in below where string_to_arrange is your string
NSArray *blowUpArray;
blowUpArray = makeArrayFromString(string_to_arrange);
blowUpArray = sortArrayAlphabetically(blowUpArray);
NSString *arrayToString= combineArrayIntoString(blowUpArray);
NSLog(#"arranged string = %#",arrayToString);
Just another example using NSMutableString and sortUsingComparator:
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:#"tomat"];
[mutableString appendString:#"o"];
NSLog(#"Orignal string: %#", mutableString);
NSMutableArray *charArray = [NSMutableArray array];
for (int i = 0; i < mutableString.length; ++i) {
[charArray addObject:[NSNumber numberWithChar:[mutableString characterAtIndex:i]]];
}
[charArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
if ([obj1 charValue] < [obj2 charValue]) return NSOrderedAscending;
return NSOrderedDescending;
}];
[mutableString setString:#""];
for (int i = 0; i < charArray.count; ++i) {
[mutableString appendFormat:#"%c", [charArray[i] charValue]];
}
NSLog(#"Sorted string: %#", mutableString);
Output:
Orignal string: tomato
Sorted string: amoott