Searching NSArray for an object - objective-c

I have NSArray consisting of NSDictionary objects. Need to find index in NSArray of object with matching key name in NSDictionary. Dictionary has only 1 element. What is the fastest way of doing that? Filter with predicate and then use indexOfObject?

That method would certainly work, but if you're looking for speed, you need to change your structure. Arrays aren't meant to be searched this way. However, it's what NSDictionary was built for. If you have a unique key you're searching for, why not store your dictionaries in an NSDictionary and use the much, much faster objectForKey: method?
If you also need to maintain an ordering, you could create a custom "ordered dictionary" class using an NSMutableArray of the keys in your dictionary.

Related

NSMutableDictionary Sorted Keys and Objects did not Creating

I have an array for users, I want create a contact list.
I'm sorting objects and keys alphabetically.
NSArray *sortedKeys = [[contactListDictionary allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)];
NSArray *objects = [contactListDictionary objectsForKeys:sortedKeys notFoundMarker:[NSNull null]];
After this, I can initialize dictionary again with sorted keys and
objects.
contactListDictionary = [NSMutableDictionary dictionaryWithObjects:objects forKeys:sortedKeys];
But it did not sorting keys and objects. They are mixing in NSMutableDictionary, what can I do for this situation ?
You can't do anything about this, that is, not in the way you are now trying to.
The NSDictionary class does not allow you to tell it in what order to store its keys; that's just not the way it is implemented.
But you already found out that you can get the keys, in the desired order, in an array. There should be no need for the dictionary itself to be ordered, its purpose is to give you a fast lookup mechanimsm, and it does. If you want, for example, to display the keys in order, simply create a (temporary) array created the way you already now how to.

object arranging in NSMutableDictionary

here is my dictionary and its values
NSMutableDictionary *myDic=[NSMutableDictionary Dictionary];
[myDIC setObject:#""];
[myDIC setObject:string1 forKey:key1];
[myDIC setObject:string2 forKey:key2];
[myDIC setObject:string3 forKey:key3];
so up to here i have filled up my dictionary.now i want to read them through a for loop.
for (NSString *key in myDic ){
}
here is my problem! inside this loop the my first key will be key1 but i seems it start from the last key that i have set before!
is there anyone who can tell me why ? and how i can meet my expectation as what i explained?
NSDictionary is not an index base collection it's a Hashtable, and like all HashTable, the elements are store according to some logic base on some Hash that you don't know. If you look in the documentation for NSDictionary you will find a sentence that state that there is not guaranty about the order into which the item will be retrieve.
If you want your key to be retrieve in a specific order you will need to keep your keys in an NSArray, in the order that you want them.
Or you can sort your keys when you need them.
NSArray * allKeys = [myDict allKeys];
allKeys = [allKeys sortedArrayUsing// [see the documentation for all options][1] ];
I came across this problem before. The order of a specific element in NSArray of NSMutableArray is decided by its index.
But unlike NSArray or NSMutableArray,The elements order in NSMutableDictionary or NSDictionary is undefined and nobody knows because its mechanism.
I chose a paragraph from Mac OS X Developer Libary for you:
"Internally, a dictionary uses a hash table to organize its storage
and to provide rapid access to a value given the corresponding key.
However, the methods defined for dictionaries insulate you from the
complexities of working with hash tables, hashing functions, or the
hashed value of keys. The methods take keys directly, not in their
hashed form."

Better way to convert NSArray of NSNumbers to array of NSStrings

I have an NSArray consisting of NSNumbers and I want to convert this to an NSArray of NSStrings, by getting the stringValue of each NSNumber in the first array.
The method that comes to my mind is iterating each value in the first one, getting its string value and adding it into another array. But there should be a more elegant solution for this. Do you know one?
NSArray implements the Key-Value Coding method valueForKey: in such a way that it returns a new array. The new array contains the results of asking each object in the original array for the specified value. In this case, NSNumber has its stringValue, so all you have to do is:
NSArray * b = [a valueForKey:#"stringValue"];
Plain old fast enumeration (or enumerateObjectsUsingBlock:) wouldn't be a terrible solution, though. NSArray's implementation of valueForKey: most likely uses a for loop internally, and that would be pretty readily understood by anyone who reads it later.

Check for duplicate NSStrings on a NSMutableArray

I got a NSMutableArray which I want to add strings to. I need to check if that string already exists on the array before adding ths string to it. Does anyway know a good way to do it?
Thanks!
If order doesn't matter, the simplest way would be to switch to using an NSMutableSet. Sets are unordered and NSSets and NSMutableSets can contain each object only once. Only a counted set (NSCountedSet) can contain the same object multiple times.
If order does matter, continue using NSMutableArray, and use -containsObject: to check that the object is not already there before adding it.
Edit: And as of Lion, we now have NSOrderedSet and NSMutableOrderedSet! Chocolate in my peanut butter! Peanut butter in my chocolate!
Like an unordered set, you get fast membership testing, the prohibition of duplicates, and, of course, set operations (union, intersection, etc.). Like an array, you get ordered access, including both reliable-order enumeration and access by index.
So, if you need to reject duplicates but at the same time preserve order, Lion's NS{,Mutable}OrderedSet classes are for you.
If you just want to do what you stated once, just use containsObject:, as in
if (![myArray containsObject:theObject]) [myArray addObject:theObject];
Note that this does a linear search through the array, and thus isn't appropriate if you're going to be using this operation a lot. If you are, and you don't need ordering, you should use NSSet. If you do need ordering, you could use both an NSArray and NSSet that are kept in sync (e.g. always add/delete the same object from both collections at the same time).
I preferred the NSPredicate which describe in here
In short
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"Ben", #"Adam", #"Melissa", nil];
NSPredicate *bPredicate = [NSPredicate predicateWithFormat:#"SELF MATCHES[c] %#", your_search_key];
NSArray *beginWithB = [array filteredArrayUsingPredicate:bPredicate];
if ([beginWithB count] > 0)
{
//Handle duplicate
}

Make unique NSMutableArray or NSMutableSet

I'm currently enumerating through NSMutableArray (or NSMutableSet) elements to find duplicates and remove them.
For example, if array/set has values [#"a", #"b", #"b", #"c"], the end result should be [#"a", #"b", #"c"].
Since I'm comparing NSStrings, I'm using isEqualTo: method to check if strings are equal.
Is there a more efficient way to do remove duplicate entries than to loop through all of them and check if duplicate exists?
An NSSet does exactly what you're trying to do: it is a (unordered) collection of unique items. So, you can find the unique items in your array like so:
NSSet *uniqueElements = [NSSet setWithArray:myArray];
// iterate over the unique items
for(id element in uniqueElements) {
// do something
}
NSSet most likely uses a hash algorithm to make insertion O(1) (compared to O(n^2) to check if each item is unique by iteration), but the Apple documentation does not make such a guarantee so you probably shouldn't count on that implementation detail.
If, for some reason you need to keep the unique items in a sorted (ordered) collection, you can turn the set back into an array with -[NSSet allObjects] and then sort the resulting array.
An NSSet or NSMutableSet will guarantee that you don't have duplicate objects. It will work for NSStrings as in your example, but for your own classes keep in mind what do you mean by "equal" and implement the hash and isEqual: methods accordingly.
A set never contains duplicate elements, so simply creating an NSMutableSet should guarantee uniqueness of values.
Only this line of code will work fine .
NSSet *mySet = [NSSet setWithArray:myArray];
now mySet will have unique elements.