How does NSDictionary serialization decides between 2 arrays (one of keys one for values) and one list of key/values? - serialization

When one nsdictionary is serialized (in plist) there are two options :
one boolean followed by two arrays (one for keys then the other for
values)
a list of key/values entreies
http://www.monobjc.net/xib-file-format.html
How does serialization tools decide between the two ?

Related

Struct of Arrays in flatbuffer?

Let's say I have the following flatbuffer IDL file:
table Monster {
mana:short = 150;
inventory:[ubyte]; // Vector of scalars.
}
And that I want to serialize an array of 2 Monster objects in a buffer.
Apparently it is possible to create the following memory layout for the overall buffer while serializing the data:
ArrayOfUBytesForInventoryOfMonster1|ArrayOfUBytesForInventoryOfMonster2|Monster1Data|Monster2Data
Which means that now all the inventory fields lay in a contiguous memory location.
However is it possible to also do this on the mana field?
ie I want to serialize my objects with this memory representation:
ArrayOfUBytesForInventoryOfMonster1|ArrayOfUBytesForInventoryOfMonster2|Monster1ManaValue|Monster2ManaValue|Monster1Data|Monster2Data.
Which has the effect of transforming all the "mana" values into a raw array in memory.
Is it possible to do this with Flatbuffers? It seems that fields can be only be serialized after the start of the object itself
Neither will work in the way you indicated. Scalar fields like mana are always inline in the table, so will never be contiguous with similar fields. Even vectors like inventory are prefixed by a size field, so their elements are not contiguous, even though they can be adjacent since they are not inline.
If you want contiguous data, you'll explicitly have to write out a single vector of such values.

Why is Multimap not camel cased?

This one really annoys me (and my colleague).
It's not
Hashmap
Treemap
org.apache.commons.collections.Multimap
etc.
So why didn't anyone notice this naming convention flaw or is there an intention behind this typo?
It's not a typo. Guava's Multimap is not a Map, i.e. it does not extend Map interface (and it shouldn't). See Guava's wiki page on this topic:
Multimap.get(key) always returns a non-null, possibly empty collection. This doesn't imply that the multimap spends any memory associated with the key, but instead, the returned collection is a view that allows you to add associations with the key if you like.
If you prefer the more Map-like behavior of returning null for keys that aren't in the multimap, use the asMap() view to get a Map<K, Collection<V>>. (Or, to get a Map<K,List<V>> from a ListMultimap, use the static Multimaps.asMap() method. Similar methods exist for SetMultimap and SortedSetMultimap.)
Multimap.containsKey(key) is true if and only if there are any elements associated with the specified key. In particular, if a key k was previously associated with one or more values which have since been removed from the multimap, Multimap.containsKey(k) will return false.
Multimap.entries() returns all entries for all keys in the Multimap. If you want all key-collection entries, use asMap().entrySet().
Multimap.size() returns the number of entries in the entire multimap, not the number of distinct keys. Use Multimap.keySet().size() instead to get the number of distinct keys.
On the other hand, Apache Commons Collections' MultiMap (not the capital "M" in map) extends Map, but it's a bit awkward in use, plus Apache devs also came to consludion that extending and mimicking map-like behavior in multimap is not what user wants, so they deprecated MultiMap (yes, you should not use old MultiMap interface and its implementations in new code!) and now recommend using MultiValueMap instead - it does not extend Map and has quite similar API to Guava equivalent.
The word "multimap" (one word, entirely lowercase) refers to a specific data structure. It's different from a "map", which is another data structure. So since they're different data structures, they have different names.
The Map interface you usually use in Java is the chosen name for an associative array, also known as "map", "dictionary", "hash", etc. Likewise, Guava's Multimap interface is their representation of the multimap data structure.

Keeping an array sorted - at setting, getting or later?

As an aid to learning objective c/oop, I'm designing an iOS app to store and display periodic bodyweight measurements. I've got a singleton which returns a mutablearray of the shared store of measurement object. Each measurement will have at least a date and a body weight, and I want to be able to add historic measurements.
I'd like to display the measurements in date order. What's the best way to do this? As far as I can see the options are as follows: 1) when adding a measurement - I override addobject to sort the shared store every time after a measurement is added, 2) when retrieving the mutablearray I sort it, or 3) I retrieve the mutablearray in whatever order it happens to be in the shared store, then sort it when displaying the table/chart.
It's likely that the data will be retrieved more frequently than a new datum is added, so option 1 will reduce redundant sorting of the shared store - so this is the best way, yes?
You can use a modified version of (1). Instead of sorting the complete array each time a new object is inserted, you use the method described here: https://stackoverflow.com/a/8180369/1187415 to insert the new object into the array at the correct place.
Then for each insert you have only a binary search to find the correct index for the new object, and the array is always in correct order.
Since you said that the data is more frequently retrieved than new data is added, this seems to be more efficient.
If I forget your special case, this question is not so easy to answer. There are two basic solutions:
Keep array unsorted and when you try to access the element and array is not sorted, then sort it. Let's call it "lazy sorting".
Keep array sorted when inserting elements. Note this is not about appending new element at the end and then sort the whole array. This is about finding where the element should be (binary search) and place it there. Let's call it "sorted insert".
Both techniques are correct and useful and deciding which one is better depends on your use cases.
Example:
You want to insert hundreds of elements into the array, then access the elements, then again insert hundreds of elements, then access. In summary, you will be inserting values in big chunks. In this case, lazy sorting will be better.
You will often insert individual elements and you will access the elements often. Then sorted insert will have better performance.
Something in the middle (between inserting 1 and inserting tens of elements). You probably don't care which one of the methods will be used.
(Note that you can use also specialized structures to keep an array sorted, not based on NSArray, e.g. structures based on a balanced tree, while keeping number of elements in the subtree).

Is there any built in method for sorting in Objective-c?

I have two sorted NSMutableArrays (or I can use any other collection, not critical), I need to insert objects from the first array to the second and preserve sort order in the second array. What is the optimal (fastest) method to do that? I can implement all the known good algorithms, but my question is, if there is already some built-in method? If not, what is the best algorithm in my case?
The real answer would be: it depends, since you are asking: what is the fastest way of inserting objects from one array into another while preserving sort order.
There is no built in way of inserting in the right place of a sorted array. You can achieve the same effect by just adding the two arrays together but it won't be "the fastest way".
What is actually faster depends on many things like: how much data does the arrays contain, what is the ratio of data in array1 vs array2 (does one array contain much more data than the other)?, etc.
NOTE: You should probably begin with the simple solution and only optimize once you experience performance problems. Do measurements with a large data set though, to see that your solution works with whatever data your users may have.
Inserting items from one sorted array into another sorted array
If you want to merge the two arrays by inserting objects in the right place then normal algorithms apply. You should insert the smaller array into the bigger array and try to insert entire sorted sequences where possible instead of every item one by one.
For best performance you should try to make a batch insert using insertObjects:atIndexes: instead of inserting the object one by one.
You can use indexOfObject:inSortedRange:options:usingComparator: to find the index that each item should be inserted in the other array if you specify NSBinarySearchingInsertionIndex for the options. Also, the comparator you are using must be the same as the comparator that sorted the array, otherwise the result is "undefined".
With this in mind you would do something like this
Create mutable index
For every ITEM in SMALLER ARRAY
Find the index where to insert ITEM in LONGER ARRAY
Add (the insertion location + the location in the short array) as the index in the mutable set.
Next item.
Batch insert all items.
The documentation for insertObjects:atIndexes: tells you that "the corresponding location specified in indexes after earlier insertions have been made." Which in your case with two sorted array mean all items with a lower index will already have been added and thus you should add the index of the object in the short array to the value returned from indexOfObject:inSortedRange:options:usingComparator:.
Another (probably very premature optimization) you can do is decrease the sortedRange for every item in the loop so that you don't have to search through parts of the array that you know the item to be inserted is bigger than.
There are probably many other optimizations that can be made. You should still measure first! Hopefully this will get you started.
NSArray *newArray=[firstArray arrayByAddingObjectsFromArray:secondArray];
newArray = [newArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
I would start by simply adding all of the objects of the first array to the second and then resorting the second. Time how long it takes. If it is acceptable, stop there.
If not, you could try a binary search to find the insertion point in the second array for each item in the first array. Since both arrays are sorted, you might be able to optimise the search by using the last insertion point as the lower bound each time round. Something like this:
NSInteger insertionPoint = -1;
for (id object in array1)
{
insertionPoint = [self binarySearch: array2 for: object lowerBound: insertionPoint + 1];
[array2 insertObject: object atIndex: insertionPoint];
}
The Cocoa class NSSortDescriptor together with sortedArrayUsingDescriptors: from NSArray should do what you are after.
Since you are using mutable arrays, you might want to use sortUsingDescriptors: which sorts the mutable array without creating a new one.
Look at the documentation here to see if any of the NSArray sort methods work for you. http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html. You can scroll down to the methods and there's 7 built-in ones for sorting. You could probably just combine the two arrays and run the sortedArrayUsingComparator: or one of the other methods.

Overriding CompareTo when there are multiple ways to compare two objects of the same type?

What's a sound approach to override the CompareTo() method in a custom class with multiple approaches to comparing the data contained in the class? I'm attempting to implement IComparable(Of T) just so I have a few of the baseline interfaces implemented. Not planning on doing any sorting yet, but this will save me down the road if I need to.
Reading MSDN states mostly that we have to return 0 if the objects are equal, -1 if obj1 is less than obj2, or 1 is obj1 is greater than obj2. But that's rather simplistic.
Consider an IPv4 address (which is what I'm implementing in my class). There's two main numbers to consider -- the IP address itself, and the CIDR. An IPv4 address by itself is assumed to have a CIDR of /32, so in that case, in a CompareTo method, I can just compare the addresses directly to determine if one is greater or less than the other. But when the CIDR's are different, then things get tricky.
Assume obj1 is 10.0.0.0/8 and obj2 is 192.168.75.0/24. I could compare these two addresses a number of ways. I could just ignore the CIDR, and still regard as obj2 as being greater than obj1. I could compare them based on their CIDR, which would be comparing the size of the network (and a /8 will trump a /24 quite easily). I could compare them on both their numerical address AND their CIDR, on the off chance obj2 was actually an address inside the network defined by obj1.
What's the kind of approach used to handle situations like this? Can I define two CompareTo methods, overloaded, such that one would evaluate one address relative to another address, and the second would evaluate the size of the overall network? How would the .NET framework be told which one to use depending on how one might want to sort an array? Or do some other function that relies on CompareTo()?
For CompareTo, you should use a comparison that represents the default, normal sort order for a particular type. For example, in the example you gave, I would probably expect it to sort on the address first, then on the subnet size.
But for the case where there is no obvious "default" sort order, or when there are multiple ways to compare (such as case sensitive or not when comparing strings) the recommended approach is to use an IComparer<T>. This would be a separate object that is able to compare two instances of your type. For example, a AddressComparer or SubnetComparer. You could even make them static properties of a class which is what StringComparer does.
Just about all methods that take IComparable types should also have an overload that allows you to specify an IComparer to use instead. You don't have to implement both, but if it makes sense, do it. That way you can specify a particular comparer when needed or use the default built-in IComparable logic of your type.