Sorting an NSArray by an NSDictionary value - objective-c

I'm trying to sort an array that would look something like this:
(please ignore the fact these people are well past any living age! I just needed large numbers)
NSDictionary *person1 = [NSDictionary dictionaryWithObjectsAndKeys:#"sam",#"name",#"28.00",#"age",nil];
NSDictionary *person2 = [NSDictionary dictionaryWithObjectsAndKeys:#"cody",#"name",#"100.00",#"age",nil];
NSDictionary *person3 = [NSDictionary dictionaryWithObjectsAndKeys:#"marvin",#"name",#"299.00",#"age",nil];
NSDictionary *person4 = [NSDictionary dictionaryWithObjectsAndKeys:#"billy",#"name",#"0.0",#"age",nil];
NSDictionary *person5 = [NSDictionary dictionaryWithObjectsAndKeys:#"tammy",#"name",#"54.00",#"age",nil];
NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:person1,person2,person3,person4,person5,nil];
// before sort
NSLog(#"%#",arr);
NSSortDescriptor *ageSorter = [[NSSortDescriptor alloc] initWithKey:#"age" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:ageSorter]];
// after sort
NSLog(#"%#",arr);
Now before sort the output would be:
2010-07-21 10:46:31.898 Sorting[70673:207] (
{
age = "28.00";
name = sam;
},
{
age = "100.00";
name = cody;
},
{
age = "299.00";
name = marvin;
},
{
age = "0.0";
name = billy;
},
{
age = "54.00";
name = tammy;
}
)
and after the sort:
2010-07-21 10:46:31.900 Sorting[70673:207] (
{
age = "0.0";
name = billy;
},
{
age = "100.00";
name = cody;
},
{
age = "28.00";
name = sam;
},
{
age = "299.00";
name = marvin;
},
{
age = "54.00";
name = tammy;
}
)
As you can see it does sort it, but from my understanding it's sorting by string. I've tried but after a few days of failure of trying to write a method that would sort this for me im still at a loss. What would be the best approach and accomplishing this so it sorts by a numeric value?

Although I question the use of strings here, the simplest way to work with that data with be:
[array sortedArrayUsingComparator:^(NSDictionary *item1, NSDictionary *item2) {
NSString *age1 = [item1 objectForKey:#"age"];
NSString *age2 = [item2 objectForKey:#"age"];
return [age1 compare:age2 options:NSNumericSearch];
}];
Or, using Objective-C's more recent subscripting features:
[array sortedArrayUsingComparator:^(NSDictionary *item1, NSDictionary *item2) {
return [item1[#"age"] compare:item2[#"age"] options:NSNumericSearch];
}];

Easiest would be storing the age as a number instead of a string.

Related

Sort the Main NSArray using the SubArray key value pair

I want to sort my main array depending on the first_name in the array self.contacts
Code that is used to sort the array
-(void)Sort
{
NSSortDescriptor *sdName = [[NSSortDescriptor alloc] initWithKey:#"first_name" ascending:YES];
self.contacts = [NSMutableArray arrayWithArray:[self.contacts sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sdName, nil]]];
}
MyData
self.contacts = (
{
contact = {
"first_name" = "Test R";
};
"last_met" = (
{
"last_met_date" = "2014-10-09";
}
);
},
{
contact = {
"first_name" = "Test K";
};
"last_met" = (
{
"last_met_date" = "2014-10-09";
}
);
}
)
Try with this sort descriptor:
descriptor = [[NSSortDescriptor alloc] initWithKey:#"contact.first_name"
ascending:YES];
The parameter key is actually a key path, and NSDictionary is KV compliant. You can write stuff like: [contacts[0] valueForKeyPath:#"contact.first_name"].
Looking on your code it looks like that you want to sort your contacts array, which is an array of dictionaries, the solution I provide here is for that case.
You can do it like this:
NSArray *sortedContactsArray = [self.contacts sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString *first_name1 = [obj1 valueForKeyPath:#"contact.first_name"];
NSString *first_name2 = [obj2 valueForKeyPath:#"contact.first_name"];
return [first_name1 compare:first_name2];
}];
Note, that it could be not safe and optimal, but that's just one of the ways to do it.

How to parse JSON

How to parse this below "choices" on one array means when I have get "id" in array that all id values 108,109.... in 1st index in array but here is the 5 values in choices..so how to parse it
choices = (
{
id = 108;
label = Distributor;
},
{
id = 109;
label = "Clinical Lab";
},
{
id = 110;
label = Researcher;
},
{
id = 111;
label = "Current Customer";
},
{
id = 112;
label = "Past Customer";
}
);
Get in a single Step bro as
If your array is NSMutableArray then use as
NSArray *resultArray = [[NSArray arrayWithArray:temp] valueForKeyPath:#"id"]
If simple NSArray then use as
NSArray *resultArray = [jsonArray valueForKeyPath:#"id"]
You can do it using fast enumeration.
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithCapacity:0];
// JSONDict is your JSON dict
for (NSDictionary *aDict in JSONDict[#"choices"]) {
[resultArray addObject:aDict[#"id"]];
}
NSLog(#"%#", resultArray);
Output:
(
108,
109,
110,
111,
112
)
If i understand your question properly, Then You can try this code for getting Ids in a Array:
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (int i = 0;i<[choices count];i++)
{
[arr addObject:[[choices objectAtIndex:i] objectForKey:#"id"]];
}
NSLog(#"ID array : %#",arr);
[arr release];
try like this ,
NSMutableArray *idArray=[[NSMutableArray alloc]init];
for(int i=0;i<[jsonArray count];i++)
[idArray addObject:[[jsonArray objectAtIndex:i] valueForKey:#"id"]];
NSLog(#"%#",idArray);
here you'l get all the values in idArray.

objective-c: read an array create by json

I begin in Ios dev and I got some troubles to manipulate an array create by Json :
I call in my app a web Service which return me data :
{evenements =(
({
dateEvenement ={
1 = "01-01-2013";
2 = "02-01-2013";
3 = "03-01-2013";
4 = "04-01-2013";
};
idEvenement = 61;
nbrInvite = 1;
nomEvenement = "My event Name";
nomUtilisateur = "Lucas ";
}
),
);
}
I'm able to get all the values by the following code except for "dateEvenement" :
NSArray *msgList;
msgList = [ jsonResults objectForKey:#"evenements" ];
for (NSDictionary *evenements in msgList) {
for (NSDictionary *evenement in evenements ) {
NSString *idEvenement = [evenement objectForKey:#"idEvenement"];
NSString *nomUtilisateur = [evenement objectForKey:#"nomUtilisateur"];
NSString *nomEvenement = [evenement objectForKey:#"nomEvenement"];
NSString *nbrInvite = [evenement objectForKey:#"nbrInvite"];
NSArray *dates = [ evenement objectForKey:#"dateEvenement" ];
}
}
Can you help me for getting datas of "dateEvenement"
Well in your JSON the dateEvenement isn't an Array but a dictionary:
NSDictionary *dates = [ evenement objectForKey:#"dateEvenement"];
for(NSNumber *key in dates) {
NSString *dateString = [dates objectForKey:key];
NSLog(%# : %#, key, dateString);
}
As declared in your JSON example the key's for the dictionary are numbers, thus you should NSNumber object for the key type.

NSArray and NSDictionary

I have NSDictionaries in NSArray just like below.
array(dictionary("user":1, "p1":1), dictionary("user":2, "p1":3),
dictionary("user":1, "p1":5), dictionary("user":2, "p1":7))
And I want to turn this array into dictionary like below.
NSArray *u1 = [NSArray arrayWithObjects:#"1", #"5", nil];
NSArray *u2 = [NSArray arrayWithObjects:#"3", #"7", nil];
keys = [NSArray arrayWithObjects:#"u1", #"u2", nil];
points = [NSDictionary dictionaryWithObjectsAndKeys:u1, #"u1", u2, #"u2", nil];
How can I do that? I am lost, can you guys please help me?
Couldn't you just iterate over your original array, asking each dictionary if the object for key "user" is 1, and if so, copy the object into a new array at index 0? Or if your user numbers are in counting order, maybe even have the index number equal the user number. Then repeat for "user" = 2, etc. Then make a dictionary so that each key/object pair is created by keys from the keys array (keys[i]) and objects from your new array (objects[i]).
What have you tried?
Here is some code typed directly into the answer, so it has not be tested:
You haven't given a name for your original array, so let's assume it is:
NSArray *originalArray;
We need a mutable dictionary to store the result:
NSMutableDictionary *points = [NSMutableDictionary new];
Now we need to process every element in the original array and it is a dictionary:
for(NSDictionary *item in originalArray)
{
Get the current entry in points array that matches item. You don't give types for your entries, so we'll use id:
id currentUser = [item objectForKey:#"user"];
NSMutableArray *currentValues = [points objectForKey:currentUser];
If this is the first occurrence of currentUser then currentValues will be nil, and we need to create an array for the p1 value and add it to points:
if (currentValues == nil)
[points addObject:[NSMutableArray arrayWithObject:[item objectForKey:#"p1"]
forKey:currentUser
]
]
Otherwise we just add the p1 value to the array:
else
[currentValues setObject:[item objectForKey:#"p1"]];
close out the loop and get the keys:
}
NSArray *keys = [points allKeys];
Now if you're using Xcode 4.5 you can use modern syntax for some of that:
NSMutableDictionary *points = [NSMutableDictionary new];
for(NSDictionary *item in originalArray)
{
id currentUser = item[#"user"];
NSMutableArray *currentValues = points[currentUser];
if (currentValues == nil)
points[currentUser] = [NSMutableArray arrayWithObject:item[#"p1"];
else
[currentValues addObject:item[#"p1"]];
}
NSArray *keys = [points allKeys];
HTH
Another possible solution (works with an arbitrary number of users):
NSArray *orig = #[
#{#"user" : #"1", #"p1" : #"1"},
#{#"user" : #"2", #"p1" : #"3"},
#{#"user" : #"1", #"p1" : #"5"},
#{#"user" : #"2", #"p1" : #"7"},
];
// Create set of all users (without duplicates)
NSSet *users = [NSSet setWithArray:[orig valueForKey:#"user"]];
NSMutableDictionary *points = [NSMutableDictionary dictionary];
for (NSString *user in users) {
// newKey = "u" + username, e.g. "u1" or "u2":
NSString *newKey = [#"u" stringByAppendingString:user];
// newValue = array of "p1" values of the current user:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"user == %#", user];
NSArray *newValue = [[orig filteredArrayUsingPredicate:pred] valueForKey:#"p1"];
// Add to dictionary:
[points setObject:newValue forKey:newKey];
}
NSLog(#"%#", points);
Output:
{
u1 = (
1,
5
);
u2 = (
3,
7
);
}
And the keys can be obtained by
NSArray *keys = [points allKeys];
You can do, like this (code not tested)
NSMutableArray *keys=[NSMutableArray new];
NSMutableArray *u1=[NSMutableArray new];
NSMutableArray *u2=[NSMutableArray new];
NSMutableDictionary *points=[NSMutableDictionary new];
for (id dict in array){
NSString *user=[dict objectForKey:#"user"];
NSString *p1=[dict objectForKey:#"p1"];
[keys addObject:[NSString stringWithFormat:#"%#",user]];
if( [user isEqualToString:#"1"] ){
[u1 addObject:user];
}
else{
[u2 addObject:user];
}
}
points=[NSDictionary dictionaryWithObjectsAndKeys:u1,#"u1",u2, #"u2", nil];
Tons of approaches. Here's another:
NSArray *originalArray = #[
#{#"user":#"u1", #"p1":#"1"},
#{#"user":#"u2", #"p1":#"3"},
#{#"user":#"u1", #"p1":#"5"},
#{#"user":#"u2", #"p1":#"7"}
];
NSLog(#"originalArray = %#", originalArray);
NSMutableDictionary *results = [NSMutableDictionary dictionary];
for (NSDictionary *dictionary in originalArray) {
NSString *user = dictionary[#"user"];
NSString *p1 = dictionary[#"p1"];
if (!results[user])
results[user] = [NSMutableArray array];
[results[user] addObject:p1];
}
NSLog(#"results = %#", results);
That takes:
originalArray = (
{
p1 = 1;
user = u1;
},
{
p1 = 3;
user = u2;
},
{
p1 = 5;
user = u1;
},
{
p1 = 7;
user = u2;
}
)
And gives
results = {
u1 = (
1,
5
);
u2 = (
3,
7
);
}

how to Json request convert to native object or list?

{
"id": "1",
"result": [
{
"Name": "John",
"Statu": "Online"
},
{
"Name": "Alex",
"Statu": "Online"
},
{
"Name": "Diaz",
"Statu": "Offline"
}
]
}
How do i extract each "car" JSON object and put it into a native object? I tried several way but i can't do that.
NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSString *responseDict = [responseString JSONValue];
NSArray *objects = [NSArray arrayWithObjects:[responseDict valueForKeyPath:#"result.Name"],[responseDict valueForKeyPath:#"result.Statu"],nil];
NSLog(#"objects Array: %#",objects);
**==> NSLOG gives:
(
(
"John",
"Alex",
"Diaz"
),
(
"Online",
"Online",
"Offline"
)
)
NSArray *resultsArray = [responseString JSONValue];
for (NSDictionary *personDict in resultsArray)
{
NSLog(#"ihaleAdi =: %#",[carDict valueForKey:#"result.ihaleAdi"]);
NSLog(#"ihaleDurum =: %#",[carDict valueForKey:#"result.Statu"]);
}
But ıt gıves an error tooç I want to just lıst them but ı cant do thatç can anybody help me please? thank you for reading
Use an Array to capture the responseString:
NSString *responseString = [request responseString];
NSArray *array = [responseString JSONValue];
Then when you need an individual item from that array use a Dictionary:
// 0 is the index of the array you need
NSDictionary *itemDictionary = (NSDictionary *)[array objectAtIndex:0];
Given a JSON responseString that looks like this:
[{"UniqueID":111111,"DeviceName":"DeviceName1","Location":"Device1Loc","Description":"Device1Desc"},{"UniqueID":22222,"DeviceName":"DeviceName2","Location":"Device2Loc","Description":"Device2Desc"}]
You will wind up with an Array that looks like this:
myArray = (
{
Description = "Device1Desc";
DeviceName = "DeviceName1";
Location = "Device1Loc";
UniqueID = 111111;
},
{
Description = "Device2Desc";
DeviceName = "DeviceName2";
Location = "Device2Loc";
UniqueID = 222222;
}
)
And a Dictionary of index 0 that looks like this:
myDictionary = {
Description = "Device1Desc";
DeviceName = "DeviceName1";
Location = "Device1Loc";
UniqueID = 111111;
}
Sorry for any confusion and improperly instantiated object earlier. I am still a relative newbie that learned something today.