My problem is...
I have data that gets pulled from a XML file and parsed then stored in an array.
This data is updated every ~60 minutes.
Now i created a second array that parses the same data but only once a week.
What happens now is that i have an array that is updated every 60 minutes and another that is updated every 7 days.
The reason for this, is that i'm doing a table of teams and i want to check when a team has moved up or down in the standings.
So my first issue is tackled, i have 2 arrays containing the teams one with up to date data and the other with a week old data.
My second issue is how do i compare these objects indexes? each object has many properties, as .name or .teamid
Can someone provide me a sample code on how to compare ArrayA Object.name to ArrayB.name?
Thank you so much.
Your question is confusing; apparently you have written an application which is capable of pulling data from XML files, parsing it, creating an array, and doing all this to a time schedule and yet don't know how to compare two items? It sounds like I'm misunderstanding your question! So here is a guess, maybe it will help:
Cocoa has a pattern for equality of objects - two methods isEqual: and hash work together to provide a standardised way of testing whether two object instances are "equal", whatever that means in terms of what the objects represent.
These methods are provided by all the standard classes, so you can test whether two NSString instances represent the same string etc. For a collection class such as NSArray its isEqual: method compares the elements in the two arrays pairwise by calling their isEqual: methods etc.
The base class, NSObject, provides a default implementation, but as it cannot know what equality means for a particular class its implementation is very basic - two objects are equal if and only if they are exactly the same object, i.e. [a isEqual:a] is YES and nothing else is.
So you need to provide an isEqual: and (this is important) hash pair for your class, which implements what is equality for your class - which is probably defined in terms of some of its properties, such as the name you mention, and will invoke their isEqual: methods.
Of course if equality of your class is simply based on one of its properties, such as name, implementing isEqual: & hash is trivial - the implementations just call the same methods on that property. In this case you don't even need to implement the pair yourself, you can access the property can compare it directly. Something like:
NSUInteger indexOfInterest = ...;
MyClass *objectA = arrayA[indexOfInterest];
MyClass *objectB = arrayB[indexOfInterest];
BOOL itemsAreEqual = [objectA.name isEqual:objectB.name];
If your property is not an object type but some primitive type, such as int, then you just use the standard equality operator:
BOOL itemsAreEqual = objectA.name == objectB.name;
Read: Object Comparison from Apple's Cocoa Core Competencies.
Related
I am trying to do array comparison on 2 mutable arrays. In one of the array, i am storing my model objects and in the other array I am storing a copy of the model objects using [myObject copy]. My model object is a subclass of NSObject so I have added the copyWithZone: method as well. However when I do array compare using isEqualToArray on these two arrays it always returns false. Will the compare not work on copied objects? Or am I going wrong somewhere else?
P.S: As an overview, what I'm trying to do is to check whether something is changed in my model before calling an update service. I want to call the service Only if any of the model objects have changed.
Will the compare not work on copied objects?
You can very easily find out the answer to this question by just copying a single object and checking for equality agains the original.
SPOILER
The results you are going to see will depend on if you have implemented custom hash and isEqual: methods in your class. Without those it will default to the superclasses implementation (NSObject) which considers equality to be the same pointer. Since a copy is a new pointer to the same object, NSObject won't consider them equal.
I would recommend that you read about object equality in this NSHipster article (great to start with) and/or in this article by Mike Ash (if you are feeling curious)
Method isEqualToArray acts as follows. It takes one by one the next objects from two arrays and compare them using isEqual. The latter compares hash (NSInteger property) of NSObjects (or its subclasses).
In general it is the address of the object. hash can be redefined while subclassing but it may cause big problems.
For copied objects you will have different hashes. And thus isEqualToArray is always FALSE.
But if you use simple data classes like NSNumber, NSString as elements to compare, you will get TRUE under copying them.
I have 2 Core Data objects of the same type. I got them via different ways.
At the same time these objects have an NSString field (identifier).
So what is better?
1)compare objects via isEqual:
2)compare objects via == (is it possible in general?)
3)compare objects' fields via isEqualToString:?
Basically, never use == on objects. Always use isEqual:.
If you're using a predicate then you can use LIKE on the identifier.
If you are trying to determine whether or not two objects are the semantically equal and you can describe what equality looks like for that type, then use isEqual. For example, if you have a Person class, you might define equality based on SSN (in the US) or something equally unique.
If you are trying to determine that two objects have something specific in common, but it doesn't necessarily imply that they are equal (for example, using the same Person example, if you want find out if two instances have the same last name), compare the attributes using isEqualToString:. It would not make sense to put this comparison into isEqual for the type.
If you are trying to find out if you have two NSManagedObject instances from your persistent store that are actually the same object fetched via different NSManagedObjectContexts, use the objectID for comparison.
I have 2 types of objects.
Class A is a subclass of NSManagedObject.
Class B is a subclass of NSObject.
S(A) is an NSSet containing objects of class A.
S(B) is an NSSet containing objects of class B.
I have a custom comparator on class A to figure out if it matches an object of class B.
I need to filter S(A) such that after the filtering operation, only those objects remain in S(A) which have a valid match in S(B).
My current naive solution iterates over S(A), and for each object iterates over S(B) which has a time complexity of O(mn) (m is the size of S(A), n is the size of S(B)).
The biggest constraint here is that A is a subclass of NSManagedObject and therefore I cannot override the -isEqual: and -hash methods to take advantage of the -intersectSet: method on NSMutableSet.
I'm looking for a solution better than O(mn). Any leads would be greatly appreciated.
I was able to find an O(m+n) solution to this problem by using the following method.
The custom comparator between class A and B relied on a string comparison and an integer equality.
Lets say these properties are
NSString *s
NSInteger i
I created an NSMutableDictionary with objects of class A and key as a hash of the string s and integer i. This process is O(m) as it involves iteration over S(A).
After this I iterate over S(B), and create the same hash using the string s and integer i from objects of class B, and look up objects in the above create NSMutableDictionary. If a match exists, I perform desired operation. This process is O(n).
While this solution takes a larger space, but is an order of magnitude faster.
I'm facing a case in my application where I need a bidirectional dictionary data structure, that means a kind of NSDictionary where your can retrieve a key with a value and a value with a key (all values and keys are unique).
Is there such a kind of data structure in C / ObjectiveC ?
You can do it with a NSDictionary:
allKeysForObject: Returns a new array containing the keys
corresponding to all occurrences of a given object in the dictionary.
(NSArray *)allKeysForObject:(id)anObject Parameters anObject The value to look for in the dictionary. Return Value A new array
containing the keys corresponding to all occurrences of anObject in
the dictionary. If no object matching anObject is found, returns an
empty array.
Discussion Each object in the dictionary is sent an isEqual: message
to determine if it’s equal to anObject.
And:
objectForKey: Returns the value associated with a given key.
(id)objectForKey:(id)aKey Parameters aKey The key for which to return the corresponding value. Return Value The value associated with
aKey, or nil if no value is associated with aKey.
Literally, the answer is No.
As a workaround you may create a helper class which manages two dictionaries.
Another approach is to create a thin wrapper around C++ container which implement this: boost's Bimap.
When using ARC and Objective-C objects as values or keys in C++ containers, they will handle NSObjects quite nicely. That is, they take care of memory management as you would expect - and you even get "exception safety" for free. Additionally, C++ standard containers are also a tad faster, use less memory, and provide more options to optimize (e.g. custom allocators).
Is there a way to compare two objects that are generic? I'm supposed to find the largest object in a linked list. My first guess was to use the Object's class compareTo method, but I couldn't get that to work. Thanks
I assume that the language is Java. (since you mentioned Object and compareTo)
I suggest you to have a have a look into Comparator and Comparable interfaces.