Sort 4 ints, smallest to biggest - objective-c

Suppose I have 4 integers.
int a = 4;
int b = 2;
int c = 4;
int d = 1;
How can I sort these integers from smallest to biggest. The output needs to be something like this: d, b, a, c Most methods of sorting only give me the value of the sorted integer. I need to know the name.
Edit: Well, I'm writing an AI algorithm. I have 4 ints that store direction priority. (If the AI comes into a wall, it chooses the next best direction). So, I need to find the lowest int, and if the AI can't move that way, I choose the second to lowest etc.

There appears to be some confusion here; in your example a is not the "name" for the value 4, it is the name of an integer variable which currently contains 4. In other words "a" is not part of the data of your program.
What I assume you mean is you have name/value pairs which you wish to sort using the value as key. A common way to do this is to define a type for your pair, create a collection, and sort the collection.
In plain C you can declare:
typedef struct
{
char *name;
int value;
} MyPair;
You can create an array of these and sort it using standard C functions for array sorting, using just the value field as the key.
In Objective-C you can declare a class for your pair:
#interface MyPair : NSObject
{
NSString *name;
int value;
}
// methods/properties
#end
You can create an NSMutableArray of instances of MyPair and then sort the array, again you just use the value property (or instance variable) when doing the comparisons for the sort algorithm.
There are other variations of course. Once sorted you can iterate through the sorted array and display the name field/property.

Here is an objective-c approach. Unfortunately, you will not have the fun of writing the AI portion, the sorting is built into the libraries already.
int north = 1, south = 3, east = 2, west =4;
NSDictionary * nDict = [NSDictionary dictionaryWithObjectsAndKeys:#"north", #"name", [NSNumber numberWithInt:north], #"value", nil];
NSDictionary * sDict = [NSDictionary dictionaryWithObjectsAndKeys:#"south", #"name", [NSNumber numberWithInt:south], #"value", nil];
NSDictionary * eDict = [NSDictionary dictionaryWithObjectsAndKeys:#"east", #"name", [NSNumber numberWithInt:east], #"value", nil];
NSDictionary * wDict = [NSDictionary dictionaryWithObjectsAndKeys:#"west", #"name", [NSNumber numberWithInt:west], #"value", nil];
NSArray * toBeSorted = [NSArray arrayWithObjects:nDict,sDict,eDict,wDict,nil];
NSArray * sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"value" ascending:NO]];
NSArray * sorted = [toBeSorted sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sorted %#", sorted);
Output
2012-01-23 19:50:21.079 TestEnvironment[19792:207] sorted (
{
name = west;
value = 4;
},
{
name = south;
value = 3;
},
{
name = east;
value = 2;
},
{
name = north;
value = 1;
}
)
Now you can check the highest priority by
NSString * highestPriority = [[sorted objectAtIndex:0] objectForKey:#"name"];
Now you have some classes you can look up (NSArray, NSDictionary, NSSortDescriptor, NSNumber)

You've tagged this Objective-C, but you haven't written anything that suggests using Objective-C. If you want to use Objective-C, I'd put the elements into an NSMutableArray (they'll need to be converted to NSNumbers to do that), and have the array sort them, as seen here.
If you just want to put them into a straight C array, you could sort them using heapsort (), qsort(), or mergesort().

Related

How to count rows and columns C Array?

I have function
- (void)sortColor:(int [3][3])colors
Are there any ways to count the rows and columns in Objective-C?
I know this is not an nsarray.I am wondering are there any simple way to count the row and col?
i got the col but row
col = sizeof(colors[0])/sizeof(*colors[0])
can anyone help?
Assuming that you consider the first array count the row, eg: int arr[# rows][# columns] = ...
This is what you are looking for:
int rows = sizeof(arr) / sizeof(*arr);
int columns = sizeof(arr[0]) / sizeof(*arr[0]);
Not that this will simply return the size of which you created the C array at, not the number of actually existing values. If that is your goal, you do indeed need to use a different structure than what you have outlined above.
Well, there is nothing like 2D array in objective-C or Swift. This is how you can simulate the behaviour though:
NSMutableArray *row1 = [NSMutableArray arrayWithObjects:#"1", #"2", nil];
NSMutableArray *row2 = [NSMutableArray arrayWithObjects:#"3", #"4", nil];
NSMutableArray *row3 = [NSMutableArray arrayWithObjects:#"5", #"6", nil];
NSArray *multiArray = #[row1, row2, row3];
NSInteger rowCount = multiArray.count;
NSInteger columnCount = row1.count; // believing each row object have same number of objects
You get the count of items in an NSArray by using the count method. Note that int arr[3][3] is not an NSArray, it's a standard C array. You generally can't get the count of standard C arrays, you have to keep track of it yourself.

Finding minimum and maximum values in a nested NSDictionary

I have a Person NSDictionary, whose key is the Name of the person, and the object is an NSDictionary with two keys: his nickname (NSString) and his age (NSNumber).
I would like to end up with the Person dictionary sorted by the ascending order of their age, so that I could get the name of the youngest and the oldest person.
What is the best way to do it?
Thanks!
There are a few convenience methods defined in NSDictionary to sort items by values and get back the sorted keys.
See docs,
keysSortedByValueUsingComparator:
keysSortedByValueUsingSelector:
keysSortedByValueWithOptions:usingComparator:
I'm guessing you're using the modern Objective-C syntax and the age is actually represented as numbers. Here's how it looks:
[people keysSortedByValueUsingComparator:(NSDictionary *firstPerson, NSDictionary *secondPerson) {
return [firstPerson[#"age"] compare:secondPerson[#"age"]];
}];
Some languages offer sorted dictionaries, but the standard NSDictionary is inherently unsorted. You can get all the keys, sort the key array and then walk over the dictionary according to the sorted keys. (NSDictionary has several convenience methods for this use case that I didn’t know about, see Anurag’s answer.)
Your case is a bit more complex, one way to solve it is to introduce a temporary dictionary mapping ages to names. But if you’re only after the minimum and maximum ages, just iterate over all persons and keep track of the maximum & minimum ages and names:
NSString *oldestName = nil;
float maxAge = -1;
for (NSString *name in [persons allKeys]) {
NSDictionary *info = persons[name];
float age = [info[#"age"] floatValue];
if (age > maxAge) {
oldestName = info[#"nick"];
maxAge = age;
}
}
And if we get back to the idea of sorting the dictionary, this could work:
NSArray *peopleByAge = [people keysSortedByValueUsingComparator:^(id a, id b) {
// Again, see Anurag’s answer for a more concise
// solution using the compare: method on NSNumbers.
float ageA = [a objectForKey:#"age"];
float ageB = [b objectForKey:#"age"];
return (ageA > ageB) ? NSOrderedDescending
: (ageB > ageA) ? NSOrderedAscending
: NSOrderedSame;
}];
As #Zoul said the standard NSDictionary is unsorted.
To sort it you can use an array, and I do things like that
//the dictionary is called dict : in my case it is loaded from a plist file
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
//make a dicoArray that is sorted so the results are sorted
NSArray *dicoArray = [[dict allKeys] sortedArrayUsingComparator:^(id firstObject, id secondObject) {
return [((NSString *)firstObject) compare:((NSString *)secondObject) options:NSNumericSearch];
}];
check the help for all the sort options. In the presented case the dictionary is sorted with keys treated as numeric value (which was the case for me).
If you need to sort another way the list of sort possibilities is
enum {
NSCaseInsensitiveSearch = 1,
NSLiteralSearch = 2,
NSBackwardsSearch = 4,
NSAnchoredSearch = 8,
NSNumericSearch = 64,
NSDiacriticInsensitiveSearch = 128,
NSWidthInsensitiveSearch = 256,
NSForcedOrderingSearch = 512,
NSRegularExpressionSearch = 1024
};
In iOS 9.2
// Dictionary of NSNumbers
NSDictionary * phoneNumbersDict = #{#"400-234-090":67,#"701-080-080":150};
// In Ascending Order
NSArray * keysArraySortedByValue = [phoneNumbersDict keysSortedByValueUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2];
}];
// In Descending Order
NSArray * keysArraySortedByValue = [phoneNumbersDict keysSortedByValueUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj2 compare:obj1];
}];
Here is the enum for NSComparisonResults.
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
Look at the NSDictionary's method that returns keys sorted by a selector. There are more than one such method. You get an array of sorted keys, then access the first and last and have your youngest and oldest person.

Sort an NSDictionary into an NSMutableArray but keep value and key?

I'm a little confused: trying to take a list of player names and scores that I have in an NSDictionary, and sort them into score order (highest score first). I know I can't sort a Dictionary so I need to move the data into an array first, but in doing so, won't I have to lose one half of each dictionary key/value pair?
For example, let's say I have the following pairs:
Bill / 10000
John / 7500
Stan / 7500
Mark / 5000
If I go and take the scores out and sort them, then retrieve the keys later, won't John and Stan get mixed up since they had identical scores? Might it call one of them twice, etc?
I realise I can't sort the dictionary, but is there a smarter way to do this?
What you could do is to get a sorted array of your players based on their score, and then create a dictionary for each player and append them in another array. Something like this perhaps (I'm using the new literals syntax, use the old one if appropriate):
NSDictionary *scores = #{
#"Stan" : #7500,
#"Mark" : #5000,
#"John" : #7500,
#"Bill" : #10000
};
NSArray *sp = [scores keysSortedByValueUsingComparator:^(id obj1, id obj2){
return [obj2 compare:obj1];
}];
NSMutableArray *players = [NSMutableArray arrayWithCapacity:0];
for (NSString *p in sp) [players addObject:#{ #"name":p, #"score":scores[p] }];
Now your players array is:
(
{
name = Bill;
score = 10000;
},
{
name = John;
score = 7500;
},
{
name = Stan;
score = 7500;
},
{
name = Mark;
score = 5000;
}
)
PS. Is not a good idea to keep a dictionary where the keys are player names, consider that you got 2 different John players... what would happen then? Also a better solution imo would be to create a Player class and keep their data (score, name etc) as properties.
You'll have to create two arrays, one for the score and another for the player. The key point being that the player array is in the same order as the (sorted) score array. The implementation below assumes you keep the score using an NSNumber object, and is not particularly efficient as it sorts the values twice:
(untested)
NSDictionary *dict = ...; // key=player (NSString), value=score (NSNumber).
NSArray *scores = [[dict allValues] sortedArrayUsingComparator:^(id obj1, id obj2) {
return [(NSNumber *)obj2 compare:(NSNumber *)obj1];
}];
NSArray *players = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) {
return [(NSNumber *)obj2 compare:(NSNumber *)obj1];
}];

NSArray sorted by function

I have an NSArray containing several NSDictionary instances. Each NSDictionary has, among other fields, an object named rating and one numberOfVotes(both are int). How can I sort the array so it gets sorted by rating/numberOfVotes? More generically, can I sort it by doing an operation like mentioned above? Or would it be better to just add another object to each NSDictionary with the value of each operation and then sort by that?
Thanks
EDIT - I have added the following. Still not sorting properly. One question: Should this work for more than 2 objects in my array. (The number of objects will vary)
[sortedArray sortedArrayUsingComparator:^NSComparisonResult(id dict1, id dict2)
{
MyObj *obj1 = (MyObj *)dict1;
MyObj *obj2 = (MyObj *)dict2;
int rating1 = obj1.rating.intValue;
int rating2 = obj2.rating.intValue;
int number1 = obj1.number_of_votes.intValue;
int number2 = obj2.number_of_votes.intValue;
double key1 = ((double)rating1)/number1;
double key2 = ((double)rating2)/number2;
if (key1 < key2)
{
return NSOrderedDescending;
}
if (key2 < key1)
{
return NSOrderedAscending;
}
return NSOrderedSame;
}];
You can define a custom comparator to use a composite sorting key of the kind that you are looking for. If there is no good reason to have that sorting key in the dictionary, other than performing the sort, do not add an item to the dictionary.
array = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
int rating1 = [[obj1 objectForKey:#"rating"] intValue];
int numberOfVotes1 = [[obj1 objectForKey:#"numberOfVotes"] intValue];
int rating2 = [[obj2 objectForKey:#"rating"] intValue];
int numberOfVotes2 = [[obj2 objectForKey:#"numberOfVotes"] intValue];
double key1 = ((double)rating1)/numberOfVotes1;
double key2 = ((double)rating2)/numberOfVotes2;
if (key1 > key2) {
return (NSComparisonResult)NSOrderedDescending;
}
if (key1 < key2) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
Note: The sortedArrayUsingComparator: method does not sort the array in place; instead, it returns a sorted copy. If you would like an in-place sorting, use NSMutableArray.
The adequate way would be using blocks like this
NSArray *sortedArray;
sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
float first = [[(NSDictionary*)a objectForKey:#"rating"] floatValue]/
[[(NSDictionary*)a objectForKey:#"numberOfVotes"] floatValue];
float second = [[(NSDictionary*)a objectForKey:#"rating"] floatValue]/
[[(NSDictionary*)a objectForKey:#"numberOfVotes"] floatValue];
return [[NSNumber numberWithFloat:first] compare: [NSNumber numberWithFloat:second]];
}];
you may find more ways to compare:
How to sort an NSMutableArray with custom objects in it?
The family of methods you seek are prefixed with sortedArray.
For a function (which is one of multiple options), see: -[NSArray sortedArrayUsingFunction:context:].
Edit: If you want to do rating divided by numberOfVotes, you will have to sort by a function or comparator block or replace the dictionary with a model object which has a method to calculate rating / numberOfVotes.
Use NSSortDescriptor.
NSArray *sorted = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"rating" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"numberOfVotes" ascending:YES],
nil]
];
Filtering data is one of the essential tasks in computing.
You can sort it several ways.
NSPredicate
You can see examples here
NSSortDescriptor
You can see examples here
Regular Expressions
Set Operations
Key-Value Coding
Ideally, you should substitute NSDictionary by a custom object, with properties like rating and numberOfVotes. Then, you could declare a method compare: on this custom object and use as the selector to sort the array.
You can use a block code to sort the objects but abstracting the implementation into a custom object is much cleaner.
you can use NSSortDescriptor here for sorting for example your array that containing several NSDictionnaries name is dataArray.
NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:rating
ascending:YES];
NSArray * keyArrray = [NSArray arrayWithObjects:descriptor, nil];
NSArray * sortedArray = [dataArray sortedArrayUsingDescriptors:keyArrray];
With the help of NSSortDescriptor we can sort any data type key value pair.

fast enumeration for NSDictionary instance ordered by the key

Overview
I am using fast enumeration to iterate through an NSDictionary instance
I expected the NSDictionary instance to be enumerated based on the ascending order of the key but that doesn't seem to be the case
What I want to do:
I want to be able iterate through the NSDictionary instance in the ascending order of the key using fast enumeration
Note: Pls see expected output vs actual output
Questions
Am i making a mistake with my implementation ?
Does NSDictionary's fast enumeration guarantee ordering based on keys ?
If not then is there a work around for this and yet use fast enumeration ?
Example
#import<Foundation/Foundation.h>
int main()
{
system("clear");
NSDictionary *d1 = nil;
#autoreleasepool
{
d1 = [[NSDictionary alloc] initWithObjectsAndKeys: #"AAA", [NSNumber numberWithInt:10],
#"BBB", [NSNumber numberWithInt:20],
#"CCC", [NSNumber numberWithInt:30],
nil];
}
for(NSNumber* n1 in d1) //I expected fast enumeration for NSDictionary to be based on the
//ascending order of the key but that doesn't seem to be the case
{
printf("key = %p"
"\t [key intValue] = %i"
"\t value = %s\n",
n1,
[n1 intValue],
[[d1 objectForKey:n1] UTF8String]);
}
return(0);
}
Expected Output
key = 0xa83 [key intValue] = 10 value = AAA
key = 0x1483 [key intValue] = 20 value = BBB
key = 0x1e83 [key intValue] = 30 value = CCC
Actual Output
key = 0x1e83 [key intValue] = 30 value = CCC
key = 0xa83 [key intValue] = 10 value = AAA
key = 0x1483 [key intValue] = 20 value = BBB
for (NSString *key in [[d1 allKeys] sortedArrayUsingSelector:#selector(compare:)])
{
id value = [d1 valueForKey:key];
...
}
No your implementation is correct.
NSDictionary fast enumeration does not guarantee sorting (and it will not output anything in order because of implementation as hashed container).
No, you have to sort it yourself.
There is no guaranties about the order in which you will receive your object.
allKeys
Returns a new array containing the dictionary’s keys.
- (NSArray *)allKeys
Return Value
A new array containing the dictionary’s keys, or an empty array if the dictionary has no entries.
Discussion
The order of the elements in the array is not defined.
So my suggestion is, if your dictionary doesn't change often, cache an NSArray with the key in the order you want them.
If your dictionary often change, you may have to sort allKeys when you need them.