I have two NSMutableArrays. The content of the first is numerically, which is paired to the content of the second one:
First Array Second Array
45 Test45
3 Test3
1 Test1
10 Test10
20 Test20
That's the look of both arrays. Now how could I order them so numerically so they end up like:
First Array Second Array
1 Test1
3 Test3
10 Test10
20 Test20
45 Test45
Thanks!
I would put the two arrays into a dictionary as keys and values. Then you can sort the first array (acting as keys in the dictionary) and quickly access the dictionary's values in the same order. Note that this will only work if the objects in the first array support NSCopying because that's how NSDictionary works.
The following code should do it. It's actually quite short because NSDictionary offers some nice convenience methods.
// Put the two arrays into a dictionary as keys and values
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:secondArray forKeys:firstArray];
// Sort the first array
NSArray *sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
// Sort the second array based on the sorted first array
NSArray *sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
Rather than keep two parallel arrays, I'd keep a single array of model objects. Each number from the first array would be the value of one property, and each string from the second array would be the value of the other property. You could then sort on either or both properties using sort descriptors.
Generally, in Cocoa and Cocoa Touch, parallel arrays make work while model objects save work. Prefer the latter over the former wherever you can.
Related
I added sequence in NSMutableDictionary by keys
Here is the key of Dictionary
New,
To Do,
Basic,
Advanced,
In Progress,
Done
But when I print NSMutableDictionary all keys then output was different
Advanced,
In Progress,
To Do,
New,
Done,
Basic
Any solution for this ?
Dictionaries are unordered collections. The sequence of items is no guaranteed, and will not be preserved. Don't make any assumptions about the order objects are fetched from a dictionary. It is not specified and subject to change.
If you need an ordered collection, try using an array of single-element dictionaries, or an array of custom objects with a key and value property.
You can try the following or come up with own data structure if you are worried about the position of elements inside a Dictionary
You can use Array of key-value pairs like this -> [[String : AnyObject]].
Which looks like : [["New" : 1],["In Progress" : 3],...]
You can also use tuples of key and value in an Array like this -> [(key,value)]
Which looks like : [("New" , 1),("In Progress" , 3),...]
Try to get keys in this array
NSArray *orderedArr = [[dict allKeys] sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
I have a NSDictionary called productionSchedule, inside is 1 key/value pair and the key of that is called KeyValue, the value of the KayValue is 31 elements, inside each of those elements in a 2 key/value pair NSDictionary and there is a Key and Value. What I am trying to do is get the Value (which is an NSDictionary) of the Key for example FA50100. Here is a screenshot of productionSchedule
Here are items I have tried
NSDictionary *productionDictionary = [[productionSchedule valueForKey:#"KeyValue"] valueForKey:[prodSchedSortedKeys objectAtIndex:0]];
How would I get the Value based off a certain Key
This gives me all the values:
NSLog(#"%#", [[productionSchedule objectForKey:#"KeyValue"] valueForKey:#"Value"]);
I think I am just missing something inbetween KeyValue and Value
When I try this:
NSLog(#"%#", [[[productionSchedule objectForKey:#"KeyValue"] valueForKey:#"FA50100"] valueForKey:#"Value"]);
I get 31 nulls :(
A. Reading the dump
The dump is a little bit confusing because of LLDB. Let's have a look on it.
This is what you get:
productionSchedule (dictionary with 1 kvp)
[0] #"KeyValue" : 31 elements
key = #"KeyValue"
value = array of 31 elements
…
What? A dictionary with an index 0?! This is, because dictionaries are represented internally as a list of paired keys and values. Therefore this is simply the first pair of the list. Let's write it more semantically and forget the key = and value = beneath it:
productionSchedule (dictionary with 1 kvp)
#"KeyValue" : array with 31 Elements
…
So with
productionSchedule[#"KeyValue"] // evals to an array
you get an array with 31 elements. You have to access this array by an index. Let's say, you want go get the first element of this array. (Since you did not recognize the array at this layer, you did not say, what element you want. Maybe you want to search through the array. Let me know).
productionSchedule (dictionary with 1 kvp)
#"KeyValue" : 31 elements
[0] dictionary with 2 kvp
…
The first element of this array is a dictionary.
productionSchedule[#"KeyValue"][0] // evals to a dictionary
It has two kvp. Again, forget about the indexing. It is a dictionary:
productionSchedule (dictionary with 1 kvp)
#"KeyValue" : 31 elements
[0] dictionary with 2 kvp
#"Key" : #"FA50100"
…
So to get the #"FA50100", you have to do
productionSchedule[#"KeyValue"][0][#"Key"] // evals to a dictionary
B. The structure
Let me say this: The whole structure seems to be corrupted. How did you create it? Without having the full information, I would give you some advices:
a) It is completely meaningless to have a dictionary with one kvp and a meaningless key #"KeyValue". First we have to throw it away and start with the array.
b) Inside this array you have 31 elements. I assume that this is the real list. But this is modelled with a dictionary with 2 kvp. (I assume that this structure applies to the rest of the 31 elements, too.) The dictionary is like this
#"Key" : #"FA50100"
#"Value" : dictionary with 6 kvp
c) So you created a kvp inside a collection that holds kvp. What is the sence of doing so!??!
Obviously #"FA50100" is something like an id and the value referred as #"Value" is the data for this key. So simply throw away the array and stor ID and its data in a single dictionary:
#"FA50100" : dictionary with 6 kvp.
Then you can access the values for #"FA50100" simply by
NSDictionary *collection = …
collection[#"FA50100"] // gets the dictionary for FA50100
d) If c is not possible, because the id #"FA50100" can occur more than one time in the list, go back using an array and put the id into the dictionary with the 6 kvp.
But never, really never, use keys like #"Key" or #"Value" in a dictionary.
C. For Debugging
However, here's a hint, if you get lost in recursive collections: Read it from step to step and make a log on each step to get the class.
This question already has answers here:
How can I sort an NSMutableArray alphabetically?
(7 answers)
Closed 8 years ago.
I have an NSMutableArray with this values:
how, format, anderson, babilon,
I would like to know if there is a command in which you can arrange this array in alphabetical order, so that the end result of the array becomes this:
anderson, babilon, format, how
observation -> my example above 4 items are specified in an array, but actually this array can store more than 1000 items, Someone can help me?
I would like to know if there is a command in which you can arrange
this array in alphabetical order, so that the end result of the array
becomes...
Yes. If you look at the NSMutableArray documentation you'll find a list of methods that can be used for sorting. They all start with the word "sort".
Apple also provides documentation on sorting arrays in the section named Sorting Arrays in Collection Programming Topics. For example, you could use the method -sortUsingSelector: this way:
NSMutableArray *names = [#[#"how", #"anderson", #"format", #"babilon"] mutableCopy];
[names sortUsingSelector:#selector(compare:)];
I have a fairly large number of NSManagedObjects in an NSArray and need to check whether do any of them have the same value for a property. The obvious way is nested for loops however it will take ages to go through all of them as there are about a 1000 objects in the array.
for (NSManagedObject *object in array) {
for (NSManagedObject *secondObject in array {
if ([[object valueForKey:#"key"] isEqualTo:[secondObject valueForKey:#"key"]] &&
object != secondObject) {
NSLog(#"Sharing a property");
}
}
}
Any better way to do this? If there are 1000 objects that accounts to 1 000 000 comparisons, that might take some time.
You could use an NSDictionary. Each entry would be made from the following pair:
key would be equal to the selected NSManagedObjects attribute
value would be an NSArray of NSManagedObjects, that share this attribute's value
Get the list of key values for the objects in the array, then turn that into a set. If the size of the set is the same as that of the original array, there are no matches.
If you need to know which objects match, use a dictionary to create a multiset -- each key has an array of the objects as its value.
Creating your own keyed set class is also an option.
You can sort the array according to the values of that property.
Then a single loop over
the array is sufficient to find objects sharing the same value of the property.
Here is my situation:
I manipulate 6 NSMutableArrays. One of them has NSDates objects in it, the other ones have NSNumbers. When I populate them, I use addObject: for each of them, so index 0 of each array contains all the values I want for my date at index 0 in the dates array.
I want to make sure that the arrays are all sorted according to the dates array (order by date, ascending), meaning that during the sorting, if row 5 of the dates array is moved to row 1, it has to be applied to all the other arrays as well.
I was previously using CoreData, but I must not use it anymore (please don't ask why, this is off-topic ;) ). In CoreData, I could use an NSSortDescriptor, but I have no idea on how to do it with multiple NSArrays...
As always, hints/answers/solutions are always appreciated :)
This is a common problem. Use the following approach.
Encapsulate your six arrays into an object - every instance will have six properties.
Implement compare: method on this object, using [NSDate compare:] (this step can be skipped but it's cleaner this way).
Now you have only one array - sort it using the method from step 2.
I think the better solution for you to have NSArray of NSDictionary objects.
NSArray *allValues = [[NSArray alloc] init];
NSDictionary *dict = #{"Date" : [NSDate date], #"Key1" : #"Value1", #"Key2" : #"Value2"};
Then you can sort this array with sortDescriptor without any problems.
And then you can also use Comparator or Sort Desriptor as you wish.
Wrap all your items that you are storing in an array into a single object. Each one of your previous 6 arrays will be a property.
Inside that object you can implement
- (NSComparisonResult)compare:(YourClass *)otherObject {
return [self.date compare:otherObject.date];
}
You can now sort the array and they will sort by date.