How to sort UITableView sections - ios

I have an array of objects with date inside.
Now I need to group my objects in UITableView by this date.
For examle:
0-{10-14; Obj1};
1-{10-14; Obj2};
2-{10-15; Obj3};
3-{10-15; Obj4};
I need to view it on my UITableView like this
10-14
0-{10-14; Obj1};
1-{10-14; Obj2};
10-15
2-{10-15; Obj3};
3-{10-15; Obj4};
To resolve I've done next; I've splited my array into NSDictationary with this code:
NSMutableDictionary *preResult = [[NSMutableDictionary alloc] init];
for (ClientMessage *message in array) {
NSMutableArray *mArray = [preResult objectForKey:message.formattedDate];
if (mArray == nil) {
mArray = [[NSMutableArray alloc] init];
[preResult setObject: mArray forKey:message.formattedDate];
}
[mArray addObject:message];
}
And my Table view shows me what i want, but it shows in wrong order; (my array was sorted by date)
I know tha i can't sort NSDictationary, in that case how can i sort my values in table view? Or Is there another way to group my values without NSDictationary?

Once you've finished loading the dictionary with all the values, you'll want to sort each array within the dictionary...
for (NSString *key in [preResult allKeys])
{
NSMutableArray *mArray = [preResult objectForKey:key];
// sort array to achieve the desired result
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"formattedDate" ascending:YES];
NSArray *sortedArray = [mArray sortedArrayUsingDescriptors:#[sortDescriptor]];
// reset newly sorted array for key inside the dictionary
[preResult sortedArray forKey:key];
}

Related

Remove duplicates from large NSMutableArray

I have a large mutable array with lots of duplicate values in alphabetical order.
I need to be able to convert my array *Array into a new array that contains one entry for each string variant.
I am currently using:
NSArray *array = [NSArray arrayWithObjects:papersObject.paperSubject, nil];
NSCountedSet *paperSet = [[NSCountedSet alloc] initWithArray:array];
NSMutableArray *namesArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[namesSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
if ([paperSet countForObject:obj] == 1) {
[namesArray addObject:obj];
}
}];
NSLog(#"%#", namesArray);
But this returns a long list of the same array, still with duplicates.
Any ideas?
What about:
NSArray *arrayWithNoDuplicates = [[NSSet setWithArray:papersObject.paperSubject] allObjects];
A. What is namesSet? paperSet?
B. However:
NSOrderedSet *set = [NSOrderedSet orderedSetWithArray:array];
NSArray *arrayWithUniquesIsAnOrderedSet = set.array;
BTW: I would highly recommend to use an ordered set instead of an array, because an array with unique objects is an ordered set.

How to Modify this NSMutableArray?

I have a dictionary which contain this data:
(
contact={name="Lion",id="1",photo="simba.png",address="elm street"},
{name="Cat",id="2",photo="halleberry.png",address="attic"},
{name="Bat",id="3",photo="dracule.jpg",address="long way home baby"}
)
From that NSDictionary, i grab only the name and sorted it alphabetically. Like this:
(B={"Bat"}, C={"Cat"}, L={"Lion"})
This is the code i used:
NSMutableDictionary* sortedDict = [NSMutableDictionary dictionary];
for (NSDictionary* animal in dataDict[#"user"]){
NSString* name = animal[#"name"];
if (![name length])
continue;
NSRange range = [name rangeOfComposedCharacterSequenceAtIndex:0];
NSString* key = [[name substringWithRange:range] uppercaseString];
NSMutableArray* list = sortedDict[key];
if (!list){
list = [NSMutableArray array];
[sortedDict setObject:list forKey:key];
}
[list addObject:name];
Then, what i want to ask is. What i need to create an array of photos but sorted alphabetically based on the name. I mean something like this:
(B="dracule.jpg", C="halleberry.png"...etc)
I also heard that this will be more effective to use (B={name="Bat", photo="draggle.jpg"}) but don't know how i can make something like this and don't know how to call it separately. Please i need your help :"(
You can easily sort the array which contains dictionaries values, see below
//Get the contact array.
NSArray *contacts=[dic objectForKey:#"contact"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortedArray = [contacts sortedArrayUsingDescriptors:#[sortDescriptor]];
I hope it helps.

Sorting NSMutableArray with date in ios7

hi i am new in IOS i have one array name with array1. Each index of an array there is one dictionary with 4 different fields like name,date,marks,standard. these all values are in NSString format. i want to sort this array1 by date. so can any one help me to do this please
here below is some part of my code
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc]init];
NSString *myname = name.text;
NSString *marks= marks.text;
NSString *date=date.text;
NSString *address=address.text;
NSString *rID=rID.text;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyMMdd"];
NSDate *date1 = [dateFormat dateFromString:date];
[tempDict setObject:myname forKey:#"name"];
[tempDict setObject:marks forKey:#"marks"];
[tempDict setObject:date1 forKey:#"date"];
[tempDict setObject:address forKey:#"address"];
[tempDict setObject:rID forKey:#"Rid"];
[array1 addObject:tempDict];
NSSortDescriptor *sortByDate = [NSSortDescriptor sortDescriptorWithKey:#"date"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByDate];
NSArray *sortedArray = [array1 sortedArrayUsingDescriptors:sortDescriptors];
If you want to sort your array with the date then you have to create NSDate object instead of NSString
NSDate *date = [dateFormatter dateFromString:date.text];
where dateFormatter is your NSDateFormatter
I think -sortUsingComparator: is the cleanest option.
[array1 sortUsingComparator: (id obj1, id obj2) {
return [[obj1 objectFoKey: #"date"] compare: [obj2 objectForKey: #"date"]];
}];
I dont know about the size of your array but if it is not something very big, you can do this:
make a dictionary (we call it sortingDict) with number of index (in array1) as key and your date of the corresponding array object as the value. You should iterate through your array1 to do this of course. (it would be better if you create NSDate objects of your string dates by the way).
get sortingDict all values. ([sortingDict allValues]) We call this dateArray.
sort your date array using NSSortDescriptor or any other algorithm you may want to use. We call it sortedDateArray.
now in a for loop iterating through sortedDateArray you get the keys of your sortingDict in order (You can use [sortingDict allKeysForObject:] and put it in an array sortedIndices
now you have an array with indices of array1 in your desired sorted order.
reordering your initial array1 wouldn't be a problem I believe.
P.S: This is a very inefficient way that just got out of the top of my head, hope it helps.
you can do like this.. if you wanted to display in tableview than other arrays are useful.
if(array1 > 0)
{
NSMutableArray *UniqueDates = [array1 valueForKeyPath:#"#distinctUnionOfObjects.date"];
[recordDates addObjectsFromArray:UniqueDates];
NSArray *cleanedArray = [[NSSet setWithArray:recordDates] allObjects];
recordDates = [cleanedArray mutableCopy];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:NO];
[recordDates sortUsingDescriptors:[NSArray arrayWithObjects:descriptor, nil]];
[mainarray addObjectsFromArray:array1];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"date == %#", [recordDates objectAtIndex:YourIndex]];
// yourindex == indexpath.row if you are displaying in table view
NSArray *filterContacts= [array1 filteredArrayUsingPredicate:predicate];
mainarray = [filterContacts mutableCopy];
recordDates and mainarray is also mutablearray.

How to sort an array in descending order in iPhone [duplicate]

This question already has answers here:
How do I sort an NSMutableArray with custom objects in it?
(27 answers)
Sorting an NSArray in reverse order
(3 answers)
Closed 9 years ago.
I am trying to sort an array in descending order,I can sort array in ascending order,Here is my code to sort in ascending order,
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"year" ascending:NO];
NSArray * descriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
sortedArray = [array sortedArrayUsingDescriptors:descriptors];
dictionaryWithSortedYears = [[NSMutableDictionary alloc] init];
NSString *tempDateKey = nil;
for (TreeXmlDetails *list in sortedArray)
{
id obj = [dictionaryWithSortedYears objectForKey:list.year];
if(!obj)
{
if(tempDateKey == nil)
{
arrayFromList = [[NSMutableArray alloc] init];
tempDateKey = list.year;
}
}
if([list.year isEqualToString:tempDateKey])
[arrayFromList addObject:list];
else
{
[dictionaryWithSortedYears setObject:arrayFromList forKey:tempDateKey];
tempDateKey = nil;
arrayFromList = nil;
arrayFromList = [[NSMutableArray alloc] init];
tempDateKey = list.year;
[arrayFromList addObject:list];
}
}
[dictionaryWithSortedYears setObject:arrayFromList forKey:tempDateKey];
NSArray *arr = [dictionaryWithSortedYears allKeys];
sortedKeys = [[NSArray alloc] initWithArray:[arr sortedArrayUsingSelector:#selector(compare:)]];
But, I want to sort an array in descending array,Please help me.
Thanks in advnace.
From the docs:
An instance of NSSortDescriptor describes a basis for ordering objects
by specifying the property to use to compare the objects, the method
to use to compare the properties, and whether the comparison should be
ascending or descending. Instances of NSSortDescriptor are immutable.
You construct an instance of NSSortDescriptor by specifying the key
path of the property to be compared, the order of the sort (ascending
or descending), and (optionally) a selector to use to perform the
comparison.
The constructor:
initWithKey:ascending:
Returns an NSSortDescriptor object initialized with a given property
key path and sort order, and with the default comparison selector.
- (id)initWithKey:(NSString *)keyPath ascending:(BOOL)ascending
The parameter that specifies the order:
ascending YES if the receiver specifies sorting in ascending order,
otherwise NO.
And these apple docs guide you step by step on how to sort arrays:
https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/SortDescriptors/Articles/Creating.html
Use the following:
[yourArrayToBeSorted sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
return [(NSDate *)obj2 compare:(NSDate *)obj1];} ];

Split NSArray into sub-arrays based on NSDictionary key values

We have an app that calls a SOAP web service and retrieves a long list of XML, which the app then parses into an NSArray of NSDictionary objects. The NSArray contains a list of Rental Apartment information, each of which is stored into an NSDictionary.
The entire list may contain 10 different types of Apartments (i.e. 2-room, 3-room), and we need to split the NSArray into smaller NSArrays based on Room-Type, which has the key "roomType" in the NSDictionary objects.
Currently our algorithm is
Use [NSArray valueForKeyPath:#"#distinctUnionofObjects.room-type"]
to obtain a list of unique room-type values.
Loop through the list of unique room-type values
For each unique room-type value, use NSPredicate to retrieve matching items from the Original list
Our code is below (renamed for clarity):
NSArray *arrOriginal = ... ...; // Contains the Parsed XML list
NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];
NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:#"distinctUnionOfObjects.roomType"];
for(NSString *strRoomType in arrRoomTypes) {
NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:#"roomType=%#", strRoomType];
NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType]; // TAKES A LONG TIME EACH LOOP-ROUND
[marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}
However, step 3 is taking a long time as the original list may contain large amount (>100,000) of items. It seems that NSPredicate goes through the entire list for each key value. Is there a more efficient way of splitting a large NSArray into smaller NSArrays, based on NSDictionary keys?
If the order of your splited Arrays is not important, i have a solution for you:
NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
id key = [dict valueForKey:#"roomType"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];
This is quite performant
- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
NSMutableDictionary *groupedItems = [NSMutableDictionary new];
for (id item in array) {
id <NSCopying> key = keyForItemBlock(item);
NSParameterAssert(key);
NSMutableArray *arrayForKey = groupedItems[key];
if (arrayForKey == nil) {
arrayForKey = [NSMutableArray new];
groupedItems[key] = arrayForKey;
}
[arrayForKey addObject:item];
}
return groupedItems;
}
Improving #Jonathan answer
Converting array to dictionary
Maintaining the same order as it was in original array
//only to a take unique keys. (key order should be maintained)
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init];
NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary];
for (NSDictionary *eachDict in arrOriginal) {
//Collecting all unique key in order of initial array
NSString *eachKey = [eachDict objectForKey:#"roomType"];
if (![aMutableArray containsObject:eachKey]) {
[aMutableArray addObject:eachKey];
}
NSMutableArray *tmp = [grouped objectForKey:key];
tmp = [dictFromArray objectForKey:eachKey];
if (!tmp) {
tmp = [NSMutableArray array];
[dictFromArray setObject:tmp forKey:eachKey];
}
[tmp addObject:eachDict];
}
//NSLog(#"dictFromArray %#",dictFromArray);
//NSLog(#"Unique Keys :: %#",aMutableArray);
//Converting from dictionary to array again...
self.finalArray = [[NSMutableArray alloc]init];
for (NSString *uniqueKey in aMutableArray) {
NSDictionary *aUniqueKeyDict = #{#"groupKey":uniqueKey,#"featureValues":[dictFromArray objectForKey:uniqueKey]};
[self.finalArray addObject:aUniqueKeyDict];
}
Hope, It will help when client wants final array in same order as input array.

Resources