efficient storage and retrieval of large set of objects in dictionaries/arrays - ios

I am creating a data source from a user's complete set of photos stored on the device (which may number in the thousands).
For each asset, I need:
URL
latitude
longitude
timestamp
When the view loads, I will enumerate all of the assets and store these 4 pieces of data for each asset. I am wondering if there are significant differences among the options for arranging all of this data. For example:
Create 1 array, with each object in the array containing a dictionary with 4 key-value pairs.
vs.
Create 1 array, containing just the URL strings. Create 3 additional dictionaries, 1 mapping each URL string to a latitude, 1 mapping each URL string to a longitude, and 1 mapping each URL string to a timestamp.
vs.
Same as #1, but instead of adding dictionaries to the array, add instances of a custom class subclassed from NSObject and containing 4 properties.
Are there significant differences in the time required to create or read from these collections (assuming thousands of objects)? Thanks.

There are lots of ways to do this, but the simplest that would save you time and would have a very low overhead would be to create a class that holds the four properties you want to create and put them in a dictionary. Making your own object to hold these pieces of information rather than rigging together a couple arrays or dictionaries will allow for more flexibility in the future.
As you enumerate through the photos, set the objects in the dictionary with the timestamp as the key (or whatever unique property you want). You can sort the keys in O(n*(log n)) and access entries in O(1) time. Then you have a sorted list of all images, it's quick, scalable, and you can easily add more properties in the future.

Related

Best way to represent un-ordered data in a plist

I'm making a plist to hold genre synonyms. The list of synonyms for a given genre doesn't have any inherent order to it.
Should I use an array (which implies an order that doesn't exist) or a dictionary (which implies there's a corresponding value for each key, which doesn't exist).
Simply put--to store an unordered set in a plist, how should I represent it and why?
(To clarify: If there were a Set data structure in the plist editor, I would use that, but I only have Array and Dictionary to choose from.)
More details: I'm going to be looking up by the primary representation of the genre, thus the outer data structure in the plist has to be a dictionary.
But then for the synonyms, the only operation necessary is to enumerate them using a block.
So either an array or a dictionary will do. However, I'm concerned that using an array will imply an order that doesn't have any semantic meaning. On the other hand, is it a common occurrence to have dictionaries in plists that don't have a corresponding value?
Editing again to respond to Josh's comments:
I like your idea of converting into an NSSet after reading in the plist. However, I could still do that with a dictionary, right? So not sure why an array is the obvious choice.
If someone else edits the plist, they might think there's a meaning to the order, when in reality, the ordering is arbitrary.
Surprised no-one has defended using a dictionary instead of an array. Is there a reason a dictionary shouldn't be used in a plist for this purpose?
If you don't care about order, then the arbitrary order you get from building an array is equivalent to the arbitrary order you'd get by using a set. You can also very easily convert an array in a plist to an NSSet after reading it back: +[NSSet setWithArray:]
So use an array.
I would just use an array, since you say there's no corresponding key for a dictionary entry.
At the same time, if you're typing in a large number of entries into plist files (www), your fingers may get tired from dealing with the raw XML or plist editor stuff. You might want to consider a different way to save your synonyms?
Use an NSArray if lookup by item is not needed. If lookup is needed use an NSDictionary.

What is the relationship between elements of plists, arrays and dictionaries?

I've got a simple program that needs to log and persistently store 2 simple pieces of data produced each time the user selects an item in a table view. The two pieces of data are 1) the time of the tap (NSDate) and 2) the name of the item tapped (NSString). At this point, this information is in this form:
TimerEvent *latestTappedEvent = [[TimerEvent alloc] init];
latestTappedEvent.timeTapped = NSDate.date;
latestTappedEvent.activityTapped = tappedItem.itemName;
The two data pieces must remain associated with each other.
My question is this:
How do I get this data into and out of a plist, ordered chronologically?
In my research, I have only become more confused. It's just not obvious to me how to use a plist. Initially, I thought I could use an NSMutableDictionary with latestTappedEvent.timeTapped as a key, and latestTappedEvent.activityTapped as the value. But when I tried to construct the plist manually, it appears not to be possible, wanting instead a string for a key.
If anyone can help me understand this, preferably by giving a graphic representation of the relationship among these different elements, I would be forever grateful.
Dictionaries and arrays both store 'things' - and the things stored are retrieved and set by using 'something else' to do a 'lookup' on the data structure. In an array, that lookup is the index in the array where an object is stored. In tabular form:
Index Storage
0 "some string stored at index 0"
1 "some other string"
2 <some other object, stored at index 2>
To find "some string stored at index 0" you would need to know it's stored at index 0 and ask the array for the object at that index. So arrays use integers to look up objects stored in them, and these integers must be in the range of 0 to the array's count minus 1. The use of integers to look up items in the array also gives the array order - the top-to-bottom ordering you see in the table above is the same order that iterating in code would yield.
Dictionaries use arbitrary objects to do the lookup which also means there's no ordering in a dictionary, there's just a set of associations of keys and what they refer to. In tabular form:
Key Storage
"name" "a string that will be accessed using the key 'name'"
"number" <some numeric object, that will be accessed using the key 'number'>
<object> "will be accessed with key <object> which is an arbitrary object"
To get "a string that will be accessed using the key 'name'" from this dictionary, you ask the dictionary for what's stored under the key "name".
In the above examples, I gave the table heading "Index - Storage" or "Key - Storage", but to circle back to the point that these structures both store things hat are accessed using another thing, let's view the array with a more generic table:
Thing used to access the thing that's stored Thing that's stored
0 "some string stored at index 0"
1 "some other string"
2 <some other object, stored at index 2>
And again, the dictionary, with the same table:
Thing used to access the thing that's stored Thing that's stored
"name" "a string that will be accessed using the key 'name'"
"number" <some numeric object, that will be accessed using the key 'number'>
<object> "will be accessed with key <object> which is an arbitrary object"
Also, let's view your class TimerEvent in the same table:
Thing used to access the thing that's stored Thing that's stored
timeTapped <date object>
activityTapped "name of an activity"
The items in the left column are Objective-C property names, and the items on the right are the values those properties contain. Now, take another look at the dictionary - the items on the left are arbitrary values (in practice they are commonly strings) and the items on the right are other arbitrary values. Hopefully you can see the connection here - that you can generally represent an object's properties as a dictionary that maps the string representation of a property name to the value the property stores. So, if you want to represent the TimerEvent object in a dictionary, you'd end up with a representation like:
Key Object
"timeTapped" <date object>
"activityTapped" "activity name"
The tables above illustrate the commonalities and differences between arrays, dictionaries, and other objects, and show that using a dictionary to map property names to property values can represent the properties of any given object. So, how would the code to do this look? Let's say we want to represent the TimerEvent object timerEvent in an NSDictionary:
NSDictionary *timerEventRepresentation = #{ #"timeTapped": timerEvent.timeTapped,
#"activityTapped": timerEvent.activityTapped};
And here's how we could create a TimerEvent from a dictionary representation:
TimerEvent *timerEvent = [[TimerEvent alloc] init];
timerEvent.timeTapped = timerEventDictionaryRepresentation[#"timeTapped"];
timerEvent.activityTapped = timerEventDictionaryRepresentation[#"activityTapped"];
The purpose behind coercing all your objects into dictionaries is that the property list format only serializes a few classes - NSArray, NSDictionary, NSString, NSDate, NSNumber, and NSData. So we write code to represent non-supported classes using the supported ones, and vice versa, to serialize these objects in plists.
As an addendum, you mention that you need to store a record of all taps, and sort them. As I mentioned above, arrays inherently order the things they store, so that is the appropriate solution here. You'd want to build something that looked like this:
Index Item
0 <dictionary representing first tap>
1 <dictionary representing second tap>
...
n <dictionary representing n-1th tap>
In code, serializing each tap would take the same form as was described earlier, but make sure to add an extra step of calling addObject: on an NSMutableArray property with the newly-created dictionary as the parameter.

Core Data. Fastest way to fill 2 double linked entities?

I have 2 tables (and similar entities):
Category (has string property identifier)
CategoryLink (has properties category1 and category2 which are pointers to Category objects)
And I have a text file with info about categories and their links. The info about links is represented as pairs of first and second link id.
I want to fill my database using Core Data. I fill Category enough fast but I have troubles with performance with CategoryLink.
My best implementation is:
get all the categories sorted by identifier;
get the whole link info from file to an array of dictionaries, sorted by first item id;
a cycle for-each for each category from (1)
in cycle (3) I search for a second category using ID from (2) in iteration and create an object of CategoryLink entity.
The performance is too slow because there are a lot of Categories and CategoryLinks records should be inserted. So are there ways to improve the performance?
Assuming you are doing all the lookups in memory, the most important performance factor is how often you save your context.
Don't save in each iteration of your loop. Try to save in batches. The ideal number depends on the data but it is often around 500-2000.
For starters, try to save only at the end and see how long that takes.
I would iterate thorough your sorted list of dictionaries and always keep a reference to catgory1.

objective c when to use NSDictionary instead of NSArray [duplicate]

This question already has answers here:
What's the difference between a dictionary and an array?
(6 answers)
Closed 10 years ago.
I'm in a dilemma in terms of which of the two I should use. I will be retrieving a group of data via a restful API (returns json) and I'm not sure how I should store them before I display it on my UI View Table.
eg.
{"Events":[{"Id":5,"Name":"Event 1 2013"},{"Id":6,"Name":"Event 2 2013"}]}
I've been reading tutorials and some would use NSMutableArrays while some would use NSMutableDictionary.
How should I go about it?
BTW: I'm displaying the data on UI View table that will redirect the user to another page when tapped and if they decide to go back will have to show the previous view without reloading (uses UinavigationController)
Thanks!
EDIT:
Also, just to give you an idea on what I'm trying to do. I'm trying to follow this tutorial on splitting the data I get into section headers. On this tutorial it's using NSDictionary.
http://www.icodeblog.com/2010/12/10/implementing-uitableview-sections-from-an-nsarray-of-nsdictionary-objects/
If I use NSArray, would that affect the performance?
In NSArray - every item in the collection has an integer index, so there is an explicit order to the items. When you're retrieving/replacing/removing the stored object from the NSARRY,you need to specify the corresponding object index of that stored object.
NSDictionary - derived from the word called entry. Each entry consists of one object that represents the key and a second object that is that key’s value. Within a dictionary, the keys are unique. That is, no two keys in a single dictionary are equal (as determined by isEqual:).When you're retrieving the object from the dictionary you need to specify the key value for the objectForKey
Whenever if you're parsing the plist then NSDictionary would be ideal.You can refer apple's document here for more explanation about NSDictionary.Happy coding :)
The lookup times on NSDictionaries are faster than on NSArrays. That's one of the main advantages. Here's a link to the Apple documentation.
Generally, if you need to access data in an indexed fashion (like you need to for rows in a table) then you should use an array because you can access any specific index using indexOfObject:
Now, if you have a lot of information for each row then you should have an array of either custom objects or an array of dictionaries.
Dictionary are always faster than Arrays. Dictionary maps keys to objects, just like a hash table. It's an associative array.
For searching some value you need to iterate for arrays, in dictionary you retrieve it by key.
If you want the collection to be in some sorted order or arrival order then Array is the proper type for you.
Dictionary lacks when you end up getting two same keys.
And I feel good to use arrays for tableViews as I can directly associate row to index.

Is objectForKey slow for big NSDictionary?

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.

Resources