I only have a limited experience in using NSSortDescriptor.
It was sorting on one key and it worked fine.
But here is what I need now, I have a set of pairs of numbers, for example :
{(2,3), (44,5), (6,17), (33,7) ……(173,21)}
I want to sort the pairs (x,y) according to the value of a given function myfunction(x,y).
There is the trivial idea of making triplets (x,y,z) where z would be the computation of myfunction(x,y) and then sort the set of triplets, but this not what I want.
Is there a proper way to use NSSortDescriptor to do what I need?
Thanks for any information.
Unless you are using this sort descriptor with Core Data using a SQLite store, you could create a transient attribute on the object where the attribute represented z, the computation of your function. You could then sort on that transient attribute and it would produce the results you want, without storing the z values.
However, if you are using Core Data with a store like SQLite where the entire store contents are not read into memory, you cannot use transient attributes to sort on and you would have to either store your z values actually in the managed objects in order to achieve what you are describing, or read all of your managed objects into an array, and then sort that array of objects on the transient property... which would work OK if you only had a limited number of managed objects, but not so well otherwise.
Related
I have a NSManagedObject which has a (transformable) NSArray property arrayProperty.
I would like to execute a fetch request filtering for objects whose property size is less than 5. I tried
[NSPredicate predicateWithFormat:#"arrayProperty.#count <= 5"]
and
[NSPredicate predicateWithFormat:#"arrayProperty[SIZE] <= 5"]
but none of them work (giving Unsupported function expression count and Unsupported function [SIZE]).
Is there a way to achieve this?
This kind of thing isn't possible with transformable properties. Transformable are convenient for storing data, but once they're stored, that's all they are-- a bunch of bytes with no information about the data structure that created them. SQLite doesn't know that it's an array, so it's not able to do things like count how many items are in the array.
If you use transformable properties, you lose any ability to filter based on them, except for extremely basic tests like whether the value is nil.
If you need to do this kind of filtering, you'll need to consider how to change your data model. One possibility would be that instead of saving an array, create a new entity with a to-many relationship to store the values.
Suppose I have this core data structure:
code
name
address
value
is that possible to add 100 to value during the fetch? I mean, to receive a fetch results where all values are their values on the database + 100?
I know I can enumerate all results after and change the value but I am wondering if there is a way to do that while I fetch.
No, all a fetch can do is give you the literal contents of the persistent store. If you're fetching a managed object subclass you might consider adding a computed property as a category method that always returns the named field plus 100; if you're fetching dictionaries then you'll probably have to modify them yourself (which will be a hassle as they'll come back immutable).
I've just seeded 25k objects into Core Data and therefore will need to perform a comparison of some of the objects before they're fetched; though the Haversine formula. I saw a similar question that advised that all objects must be fetched and then compared, however that will be resource and memory expensive.
Please can you tell me how I can perform this custom comparison through, I assume, a predicate in this case?
Use the predicate to find objects inside a simple lat-long box (min and max values) and then apply any finer grained distance calculation, filter and sorting on the fetch results.
I don't understand why things have to be so difficult in core data. I have an entity that has 2 decimal attributes, "extended" and "qty"
All I want to do is extend these 2 values (multiply) and refer to this calculated value in a fetch. such as NSDecimalNumber * extendedPrice = [self.qty decimalNumberByMultiplyingBy:self.rate];
But in other cases I will want to #sum: this extended value attribute.
The web-available documentation and examples is very weak on how to do this which to me seems a very common thing to do.
Am I on the wrong track thinking I need a transient attribute and an awakefromfetch call? I get a crash when I try and refer to a transient attribute in a fetch.
You can't use transient attributes in fetch requests if you're using an SQLite store. This is because the fetch predicate is converted into an SQL query and no code is actually called. If the attribute doesn't exist in the store then it can't be used.
If you wanted to fetch the objects and then filter / sum them then that will work with a transient because at that point inTime you actually have the instances of the objects.
Assume we have very big NSDictionary, when we want to call the objectForKey method, will it make lots of operations in core to get value? Or will it point to value in the memory directly?
How does it works in core?
The CFDictionary section of the Collections Programming Topics for Core Foundation (which you should look into if you want to know more) states:
A dictionary—an object of the CFDictionary type—is a hashing-based
collection whose keys for accessing its values are arbitrary,
program-defined pieces of data (or pointers to data). Although the key
is usually a string (or, in Core Foundation, a CFString object), it
can be anything that can fit into the size of a pointer—an integer, a
reference to a Core Foundation object, even a pointer to a data
structure (unlikely as that might be).
This is what wikipedia has to say about hash tables:
Ideally, the hash function should map each possible key to a unique
slot index, but this ideal is rarely achievable in practice (unless
the hash keys are fixed; i.e. new entries are never added to the table
after it is created). Instead, most hash table designs assume that
hash collisions—different keys that map to the same hash value—will
occur and must be accommodated in some way. In a well-dimensioned hash
table, the average cost (number of instructions) for each lookup is
independent of the number of elements stored in the table. Many hash
table designs also allow arbitrary insertions and deletions of
key-value pairs, at constant average (indeed, amortized) cost per
operation.
The performance therefore depends on the quality of the hash. If it is good then accessing elements should be an O(1) operation (i.e. not dependent on the number of elements).
EDIT:
In fact after reading further the Collections Programming Topics for Core Foundation, apple gives an answer to your question:
The access time for a value in a CFDictionary object is guaranteed to
be at worst O(log N) for any implementation, but is often O(1)
(constant time). Insertion or deletion operations are typically in
constant time as well, but are O(N*log N) in the worst cases. It is
faster to access values through a key than accessing them directly.
Dictionaries tend to use significantly more memory than an array with
the same number of values.
NSDictionary is essentially an Hash Table structure, thus Big-O for lookup is O(1). However, to avoid reallocations (and to achieve the O(1)) complexity you should use dictionaryWithCapacity: to create a new Dictionary with appropriate size with respect to the size of your dataset.