How would you approach a problem of deriving new NSArray from existing NSArray by removing certain element from original one? I know of NSMutableArray class, but I'd like to know an approach of least moving parts.
In Deriving arrays section of NSArray documentation, there are methods like arrayByAddingObject: or arrayByAddingObjectsFromArray:. However there are no methods for deriving new arrays by removing certain objects.
You filter arrays to get rid of items.
so:
filteredArrayUsingPredicate:
seems to fit your needs. You'll need to provide a predicate, which can be anything you want it to be.
how about the next to method listed: –filteredArrayUsingPredicate: –subarrayWithRange:?
–filteredArrayUsingPredicate: will return a new array with objetcs matching the criteria defind by the predicate.
–subarrayWithRange: will give you a subarray for a certain range
You can create new array using filteredArrayUsingPredicate: method based on your criteria.
Also you can get NSIndexSet containing indexes of objects you want to keep using indexesOfObjectsPassingTest: method and then create new array from original using objectsAtIndexes: method.
Related
In my OSX app I have NSMutableSet that contains custom objects. I implemented -isEqual and -hash methods in my custom object classes, so that the set can do comparison the way I want.
However, whenever I insert a new object into my set and then call -allObjects, the array that is returned has the objects in a sorted order.
The order depends on the value of the property that I'm using for comparison of my custom objects in -isEqual method mentioned above.
In my case, I want to preserve the order at which the objects were added to the set.
Does anyone have any clue how to achieve that?
Any kind of help is highly appreciated!
Sets don't have an order, they are specifically designed to be unordered collections. When you call allObjects to get an array, the order you get is not defined so you should not depend on it.
You have 2 basic options here if you want to keep using sets.
Order the array manually once you get it.
Use an NSOrderedSet which maintains order.
In my case, I want to preserve the order at which the objects were added to the set.
Then don't use a set, but an NSArray.
Arrays store their objects in an order, sets do not.
I recently learned how to define an isEqualToCustomClass: to compare instances of that class (similar to NSString's isEqualToString:).
Many times in my project I need to compare arrays of these objects. I consider them equal if and only if the counts are the same, and the custom objects at each location are the same (the order must be identical).
What is the correct way to make this available throughout my application? Should I subclass NSArray and add a custom isEqualToArrayOfCustomThings: ? Or a category? Or some other utility class that just takes two such arrays and compares them?
-[NSArray isEqualToArray:] uses the isEqual: method of the array members to test equality with another array. If you prefer, -[NSArray isEqual:] will call through to isEqualToArray:.
All you need for this, then, is that isEqual: be implemented in your class.
N.B.: Apple advises that whenever you implement isEqual: for a class, you must also implement hash such that objects which compare as equal also have identical hashes. Mike Ash goes into some detail on this.
In my collection view I need to generate an index for each item. As Items get reordered I need this index to update with its new position.
The data are Core Data entities in a managed NSArrayController.
The closest I have come to a possible solution is implementing this method on the entity class and then using representedObject.dynamicIndex to bind it to the UI.
- (NSNumber *) dynamicIndex
{
NSInteger r = [[[[self managedObjectContext] registeredObjects] allObjects] indexOfObject:self];
NSNumber *result = [NSNumber numberWithInt:r];
return result;
}
This solution is sketchy at best, and not really functional as it doesn't necessarily reflect the order in the collection view.
Anyone have a model / mechanism for generating or retrieving item indexes in an NSCollectionView?
First, make sure you understand the difference between (and properly use the terminology of) "entity" and "instance." It makes all the difference in communicating your problems/solutions with others.
Second: Don't worry about NSCollectionViewItems ... worry about each one's "represented object," which is held in some container.
Third: Did you want the display order to be a persistent attribute of your entity or do you just need to know what position the item is in at the moment, regardless of what it might be later? Important question.
Fourth: Core Data does not give you the concept of ordered collections. This is to support store types such as NSSQLiteStoreType, where you might only want to fault in a few items (or one) without loading the whole list. Therefore, you're on your own if you want a persistent sort order. To do this, just add an attribute to your entity called "sortOrder" and make it a number type.
Fifth: Because of the "no ordered collections" issue above, your attempt to find the index of a given instance of your entity from an array, built from a set, which was faulted in with a nondeterministic order is doomed to failure.
Sixth: Since you're using an array controller, you'll need to set its sort descriptors. You'll want to use your "sortOrder" key. That way, your fetched instances will always be kept sorted by their "sortOrder."
Seventh and finally: If you're trying to get the index of any objects in your array controller's set/array of objects, you'll want to ask it for its -arrangedObjects, so you're getting the index of the object in the sorted collection the array controller controls.
Hope that helps.
Update for Lion (10.7)
With regard to my sixth point: If you're targeting 10.7 and above in your application, [NSManagedObject now gives you ordered relationships.][1] Use -mutableOrderedSetValueForKey: and -mutableOrderedSetValueForKey: to set and retrieve NSOrderedSets. Yay!
I was using NSDictionary and I observed that the objects in the dictionary are sorted automatically with respect to the keys, so my question is how to avoid this sorting, any flag available to set it off, so I get the object in same order I entered.
I know you may be thinking what difference it makes in dictionary since we retrieve the value with respect to key, but I am first getting allKeys from which I receive Array of keys, this order is what I need it to be in the order of how I entered just as in NSArray.
I guess that there will not be a method to control the sorting in NSDictionary, because 'NSDictionary' is a hash table which uses hash function to chose the place to store the values(for speedy accessing).
To customize dictionary you can use CFDictionaryRef there you can write your custom callback. You can write your own CFDictionaryHashCallBack function to compute the place for storing. CFDictionary is "toll-free bridged" with NSDictionary. RegardsDevara Gudda
I'd like to have an NSArray or NSMutableArray that always shows a filtered view of a data set. That is, if the filter is set to "show me things with the letter a", and an item "blah" is added, that item would automatically show up in the list. However, if "bluh" were added, it would not show up in the filtered list (but would still really be there in the underlying dataset).
I see that there are filter methods on NSArray and NSMutableArray, but these are one shot methods. That is, the filter occurs when you call the method and never again (unless of course you call the filter method again).
I'm coming from the Java world, were I used Glazed Lists extensively for this kind of thing. I was hoping for a similar solution baked into Cocoa.
You'll most likely want to use NSArrayController as suggested by Ole.
You can use setFilterPredicate: on it as suggested, and then you'll want to access the objects by calling arrangedObjects on the controller. You don't need setAutomaticallyRearrangesObjects: unless you're intending to have your data sorted (using sort descriptors — NSSortDescriptor instances).
NSArrayController is really set up to handle displaying things in a table view very easily, so if that's your end goal, then this is exactly what you want. It integrates nicely with NSSearchField to handle predicates in the UI.
If you're using this as some back end object that's getting passed around, then you might want to write something yourself that's a little less heavy-weight than NSArrayController.
Coming from the iPhone, I'm not very familiar with NSArrayController but you might want to take a look at it. It seems to me that setFilterPredicate: in combination with setAutomaticallyRearrangesObjects:YES might do the trick.
Other than that, it should be quite easy to roll your own solution using Key-Value Observing. Start with a mutable copy of the array you want to filter and filter it with filterUsingPredicate: as you noted above, then register yourself as an observer for insertions and deletions in the original array and when your observer method gets called, call evaluateWithObject: on the newly inserted objects to decide whether to insert them into your filtered array.