Reputation: 10245
I have a NSArray that I have parsed and sorted alphabetically from some xml I am getting from my database. I am now wondering how to split this array up for use with a index on a tableview for quicker searching.
Where my table gets a bit different is that it dosn't alway use the whole alphabet, and unlike most examples I have found the dataset I use varies alot from day to day..
so I am trying to figure out how to split a sorted array into alphabetical sections that are not always the same.
As cocofu pointed out, Yes I have got my sectionIndexTitlesForTableView already implemented, I am now trying to split my nsarray into sections so that scrolling works with sectionIndexTitlesForTableView.
Upvotes: 4
Views: 6255
Reputation: 605
"arr" here contains all the results which fetched from database or after parsing xml or whatever.
Just sort array in ascending order (arrSortedResults in my code).
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *arr=[[NSMutableArray alloc]initWithObjects:@"a",@"b",@"c",@"c",@"a1",@"b1",@"c1",@"a2",@"a3",@"a4",@"b", nil];
tableGroupView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped];//simply initialization of tableview
tableGroupView.delegate=self;
tableGroupView.dataSource=self;
[self.view addSubview:tableGroupView];
NSArray *arrSortedResults= [arr sortedArrayUsingSelector:@selector(compare:)];
ArrayForArrays=[[NSMutableArray alloc]init];//initialize a array to hold arrays for section of table view
BOOL checkValueAtIndex=NO; //flag to check
SectionHeadsKeys=[[NSMutableArray alloc]initWithObjects:nil];//initialize a array to hold keys like A,B,C ...
for(int index=0;index<[arrSortedResults count];index++)
{
NSMutableString *strchar=[arrSortedResults objectAtIndex:index];
NSString *sr=[strchar substringToIndex:1];
NSLog(@"%@",sr);//sr containing here the first character of each string
if(![SectionHeadsKeys containsObject:[sr uppercaseString]])//here I'm checking whether the character already in the selection header keys or not
{
[SectionHeadsKeys addObject:[sr uppercaseString]];
TempArrForGrouping=[[NSMutableArray alloc]initWithObjects:nil];
checkValueAtIndex=NO;
}
if([SectionHeadsKeys containsObject:[sr uppercaseString]])
{
[TempArrForGrouping addObject:[arrSortedResults objectAtIndex:index]];
if(checkValueAtIndex==NO)
{
[ArrayForArrays addObject:TempArrForGrouping];
checkValueAtIndex=YES;
}
}
}
}
//after this ArrayForArrays will contain all the arrays which will become groups under the header headerkeys
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [ArrayForArrays count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [SectionHeadsKeys objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
NSArray *arr= [ArrayForArrays objectAtIndex:section];
return [arr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell * cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil) {
cell =[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
}
int section=[indexPath section];
NSArray *arr=[ArrayForArrays objectAtIndex:section];
cell.textLabel.text=[arr objectAtIndex:indexPath.row];
return cell;
}
now output will be as bellow:
![enter image description here][1]
[1]: https://i.sstatic.net/tcPr6.png
Upvotes: -1
Reputation: 13694
You could use an NSPredicate to derive the data like so:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH 'a'"];
NSArray *aElements = [myArray filterUsingPredicate:predicate];
I would love to hear of a more efficient way instead of looping or having 26 NSPredicate Statements being run for every letter of the Alphabet or doing a loop with the characters and returning the elements.
You could store each filtered array in an NSDictionary with all the letters of the alphabet as the keys and then retrieve it later and check if it's empty (which means it has no elements for that letter). I believe BEGINSWITH is Case-Sensitive
Upvotes: 3
Reputation: 9768
I would create an NSSet with the first letters you use in your array and then create a sorted array from that. Assuming all of the first letters are of the correct case, it would look something like:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableSet *mySet = [[[NSMutableSet alloc] init] autorelease];
for ( NSString *s in myArray )
{
if ( s.length > 0 )
[mySet addObject:[s substringToIndex:1]];
}
NSArray *indexArray = [[mySet allObjects] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
return indexArray;
}
Upvotes: 6