I have an int32 attribute in a Core Data database.
I use this int as an enum bit field.
Is it possible to create a NSPredicate to query items based on the binary
value of this int ? Something like #"bitFieldAttribute & 0x0001"?
I'm also wondering if this is possible with a binary typed attribute ?
NSPredicate can handle it, but I'm not sure if CoreData will accept it as a valid predicate for execution on a data store. It might have trouble converting the bitwise operator into a SQL query (if you're using a SQLite backing store). You'll just have to try it.
The syntax, however, is just what you'd expect:
NSPredicate * p = [NSPredicate predicateWithFormat:#"(3 & 1) > 0"];
NSLog(#"%#", p);
NSLog(#"%d", [p evaluateWithObject:nil]);
Logs:
3 & 1 > 0
1
As for doing this on a binary-typed attribute (ie, one defined as data, right?) This probably won't work. Bitwise operators only really make sense when operating on integers (insofar as I understand them), so executing it on an NSData wouldn't make much sense. Convert it to a number first, and then it might work.
edit
It would appear that SQLite supports this syntax, since bitwise operators have been around since 2001, which means that Core Data will probably accept it as well.
rockfakie is so nearly right but
NSPredicate *someTypePredicate = [NSPredicate predicateWithFormat:#"(typeValue & %i) == %i", valueOneOrThree,valueOneOrThree];
Is what I needed.
Here is one example / application of this technique.
Say you have a NSManagedObject that has an integer attribute with the keypath "typeValue".
Somewhere in your code define a bitwise enumeration:
typedef enum SomeType {
SomeTypeValueOne = 0x1,
SomeTypeValueTwo = 0x2,
SomeTypeValueThree = 0x4
} SomeType;
Now to query for managed objects that are of type say One or Three but not Two, do the following:
SomeType valueOneOrThree = SomeTypeValueOne | SomeTypeValueThree;
NSPredicate *someTypePredicate = [NSPredicate predicateWithFormat:#"(typeValue & %i) == typeValue", valueOneOrThree];
// construct NSFetchRequest as normal with predicate...
I hardly doubt it.
But you may use an enum for the values stored in the attribute, and use a direct comparison instead of a bit masking.
Related
I have a Set of objects, let's say Fruits:
let uniqueFruits = Set(Fruit("Apple"), Fruit("Banana"), Fruit("Orange"))
And want to sort them based on a certain atteribute. In this case "size".
I cannot find a way to do this based on the documentation from Apple:
https://developer.apple.com/reference/foundation/nsmutableset
How can I sort a Set by a certain attribute?
You have to convert the Set to an Array.
The reason for this is the following definition:
"Sets are different in the sense that order does not matter and these
will be used in cases where order does not matter."
Whereas a set:
"... stores distinct values of the same type in a collection with no
defined ordering."
See for further information:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
In this case you will have a list of distinct values (and I consider your decision to use a NSSet as valid argument) you will have to transform your set to an array, you should not run into trouble, as your set already seems to take care of that your objects are of the same type (e.g. "Fruit").
So in this case, we will have
Define Sort Criteria
Sort the Array
I have attached a sample for both Objective-C and Swift, in case you need the one way or the other:
Objective-C Code
NSMutableSet<Fruit> *uniqueFruits = [NSMutableSet new];
[uniqueFruits addObject:[[Fruit alloc] initWithName:#"Apple"]];
[uniqueFruits addObject:[[Fruit alloc] initWithName:#"Banana"]];
[uniqueFruits addObject:[[Fruit alloc] initWithName:#"Orange"]];
// 1 Define Sort Criteria
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"size" ascending:YES]; // Key is the NSString of a certain selector. If it is an attribute of another class reference. Simply use "reference.property".
// 2 Sort the Array
NSArray<Fruit> *sortedArray = [self.uniqueFruits sortedArrayUsingDescriptors:#[descriptor]];
Swift 3 Code
let uniqueFruits = Set<Fruit>(Fruit("Apple"), Fruit("Banana"), Fruit("Orange"))
// 1 & 2 Define Sort Criteria and sort the array, using a trailing closure that sorts on a field/particular property you specify
// Be aware: result is an array
let sortedArray = uniqueFruits.sort({ $0.size < $1.size })
There is NSOrderedSet and its mutable sibling NSMutableOrderedSet which are exactly that: a set that maintains an order. The mutable ordered also has various methods to sort the set. In Swift, it's a bit awkward to use since you can't create a NSMutableOrderedSet<Fruit> and can only use it with objects anyway.
I am making a calculator that logs input in a label named "inputLabel' and then outputs the answer in a different label named "outputLabel" (similar to a graphing calculator). Once the user is finished entering the expression, the expression is stored in an NSString object and then parsed with the NSPredicate class and evaluated with the NSExpression class. What I have works, but I have noticed for particular operations the answers are not correct. For example, if the user types in "25/2" the calculator returns 12, which is obviously incorrect. However, if the user types in "25/2.0" or "25.0/2" the calculator returns 12.5 which is what I want. It seems that the NSExpression method 'expressionValueWithObject' is interpreting the operands as integers instead of floats. If this is the case, is there a way that I change the 'expressionValueWithObject'method to interpret the operands as floats?
Brain.m
-(float)performCalculation: (NSString *)operation
{
NSPredicate *parsed = [NSPredicate predicateWithFormat:[operation stringByAppendingString:#"=1.0"]];
NSExpression *inputExpressionParsed = [(NSComparisonPredicate *)parsed leftExpression];
NSNumber *result = [inputExpressionParsed expressionValueWithObject:inputExpressionParsed context:nil];
return [result floatValue];
}
ViewController.m
- (IBAction)equalsPressed:(id)sender
{
//self.inputLabel.text = [self.inputLabel.text stringByAppendingString:#".0"];
NSString *inputExpression = self.inputLabel.text;
self.inputLabel.text = [self.inputLabel.text stringByAppendingString:#"="];
float result = [self.brain performCalculation:inputExpression];
self.outputLabel.text = [NSString stringWithFormat:#"%g", result];
}
No, NSExpression cannot do that. You could try to append ".0" to all integer numbers
in the string before evaluating it, but the better solution is probably to use a "proper"
math expression parser, for example
https://github.com/davedelong/DDMathParser
You could iterate through the expression tree replacing the expression with the integer value (expressionType == NSConstantExpression). It depends a little bit of the features of your calculator, whether it is worth or not.
If I declare enum type with new NS_ENUM macro which was introduced because of stronger type check, am I able to check for this type also in runtime?
I mean, I have
typedef NS_ENUM(NSUInteger, MyNewType) {
MyNewTypeInstance1,
MyNewTypeInstance2,
MyNewTypeInstance3
};
. And I want to know that for example (NSUInteger)i = 2 is kind of MyNewType.
No. NS_ENUM is just a way of using a feature introduced to Objective-C via C++11 called "fixed underlying types" for enumerations. This ensures that the type used to store the enumerated values is of a fixed size and signedness, but it doesn't allow you to inquire about the enumerated type at runtime.
If you're interested in validating whether values are actually members of your enumeration, there are two related approaches for that. If the values are contiguous, you can write a macro that checks whether the value in question is in the valid contiguous range. Otherwise, you can take the more general (and verbose) approach that Apple takes with, e.g. UIDeviceOrientationIsValidInterfaceOrientation, and explicitly check against all valid enumerated values.
#warrenm: good ansewr
i was thinking about this:
what about adding a sort of "myLastValueJustToCheck" and check if your int is < that value?
typedef NS_ENUM(NSUInteger, MyNewType) {
MyNewTypeInstance1,
MyNewTypeInstance2,
MyNewTypeInstance3,
myLastValueJustToCheck
};
then check:
NSUInteger i = 2;
NSLog(#"is %i i in my range? %i", i, (i<myLastValueJustToCheck));
i = 3;
NSLog(#"is %i i in my range? %i", i, (i<myLastValueJustToCheck));
i = 4;
NSLog(#"is %i i in my range? %i", i, (i<myLastValueJustToCheck));
Which is quicker and less expensive for checking if an object already exists within a list. By using the NSArray contains object or by checking if a key already exists for an NSDictionary?
Also does the NSArray containObject selecter iterate through the whole array elements? Also what about checking if a key already exists within a dictionary? Does that require iterating through all the keys.
Finally, what is the best and quickest way to check if an object already exists within a large list of objects (of the same class).
Thanks in advance
According to the document of Collection Classes the NSDictionary is based on HashTables. Which means if you are searching for a key in a dictionary, the time required is mush less than iterating through an array.
So, searching for a key should be o(1+numberofcollisions). where iterating through an array is o(n). You can quick sort array then binary search it which will make the cost a lot less. However for your buck, NSDictionary (hash table) are very cheap for searching.
From Apple docs
Internally, a dictionary uses a hash table to organize its storage and to provide rapid access to a value given the corresponding key. However, the methods defined for dictionaries insulate you from the complexities of working with hash tables, hashing functions, or the hashed value of keys. The methods take keys directly, not in their hashed form.
How many values are you talking about? The difference in speed may be irrelevant, thus making the choice be the one that makes the most sense in the code. In fact, that should probably be the first priority, unless and until you know that there is a speed problem.
Short version: Use NSDictionary unless you have a specific need not to.
I would say that the fastest way would be to sort your array when you insert an object:
NSMutableArray *myArray;
[myArray addObject:someCustomObject];
[myArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
// custom compare code here
}];
While this takes performance out of inserting an object, it would greatly increase your lookup times.
To do a binary search on a NSArray:
BOOL binarySearchContains(NSArray *sortedArray, id object, NSComparator comparisonBlock)
{
// simple recursive helper function
__block BOOL (^_binaryRecurse)(NSArray *, id, int lo, int hi) = ^BOOL(NSArray *array, id object, int lo, int hi)
{
int middleIndex = ((hi - lo) / 2) + lo;
if (hi == lo || middleIndex < 0 || middleIndex >= [array count])
return NO;
int compareResult = (comparisonBlock(object, [array objectAtIndex:middleIndex]));
if (compareResult < 0)
return _binaryRecurse(array, object, lo, middleIndex - 1);
if (compareResult > 0)
return _binaryRecurse(array, object, middleIndex + 1, hi);
return YES;
};
return _binaryRecurse(sortedArray, object, 0, [sortedArray count]);
}
In my tests, the bsearch is approximately 15 times faster than -containsObject:.
I'm writing a small app for the iphone and I'm trying to write a function that will insert an NSMutableString into an NSArray in alphabetical order. Also I'll be writing a sort to sort the entire array as well. For both cases I'm wondering what the best way of comparing NSMutableStrings is. Is there a specific function I can use?
Thanks for your help.
I think you're looking for
(NSComparisonResult)[aString compare: bString];
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/nsstring_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/compare:
You can use this or one of the related methods if you're doing insertion sort. However, if you want to do a one time sort of the NSMutableArray, you can use one of the NSMutableArray sorting methods such as sortUsingComparator:.
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/instm/NSMutableArray/sortUsingComparator:
If you look under "Identifying and comparing strings" in the NSString reference, you'll find several options. They do slightly different things, since you might want to compare strings in different ways (e.g. are numbers compared in lexical or numeric order?). The most basic is compare: — you can probably start there and choose a more complicated version as needed.
I think this should work for you. This is my answer which I have taken from the link:
Comparing text in UITextView?
SOLUTION-1: I have modified it here a bit to make it more easier for your case:
Let us assume String1 is one NSString.
//Though this is a case sensitive comparison of string
BOOL boolVal = [String1 isEqualToString:#"My Default Text"];
//Here is how you can do case insensitive comparison of string:
NSComparisonResult boolVal = [String1 compare:#"My Default Text" options:NSCaseInsensitiveSearch];
if(boolVal == NSOrderedSame)
{
NSLog(#"Strings are same");
}
else
{
NSLog(#"Strings are Different");
}
Here if boolVal is NSOrderedSame then you can say that strings are same else they are different.
SOLUTION-2: Also you don't find this easy, you can refer to Macmade's answer under the same link.
Hope this helps you.
For sorting array
NSArray *sortedArray = [anArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
try BOOL ans = [str1 isEqualToString:str2];
Try NSArray's sortedArrayUsingSelector: method:
NSArray * stringArray = [NSArray arrayWithObjects:#"dddsss", #"aada", #"bbb", nil];
[stringArray sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"%#", [stringArray sortedArrayUsingSelector:#selector(compare:)]);
Out put:
(
aada,
bbb,
dddsss
)
What's more, you can use NSSortDescriptor to decide ASC or DESC order.