I have 2 different NSArray with custom objects as follows,
Item *item1 = [[Items alloc] init];
item1.number = #"1";
item1.serailNumber = #"S01";
Item *item2 = [[Items alloc] init];
item2.number = #"2";
item2.serailNumber = #"S02";
Item *item3 = [[Items alloc] init];
item3.number = #"3";
item3.serailNumber = #"S03";
Item *item4 = [[Items alloc] init];
item4.number = #"4";
item4.serailNumber = #"S04";
Item *item5 = [[Items alloc] init];
item5.number = #"5";
item5.serailNumber = #"S05";
NSArray *items = #[item1, item2, item3, item4, item5];
NSArray *specList = #[#{"number" : #"002", #"serialNumber" : #"S02"},
#{"number" : #"004", #"serialNumber" : #"S04"},
#{"number" : #"003", #"serialNumber" : #"S03"}];
Now I want to sort my items array based on specList array by comparing "number" property.
Now my expected items list is,
#[item2, item4, item3, item1, item5]
I have gone through several samples as listed below but I couldn't figure out how to compare with custom objects. Any help would be appreciated, Thanks in advance.
Sample 1
Sample 2
This should do the trick:
NSArray *sorted = [items sortedArrayUsingComparator:^NSComparisonResult(Item *item1, Item *item2) {
NSInteger indexForItemEquivalent1InSpecList = [self indexForItem:item1 inList:specList];
NSInteger indexForItemEquivalent2InSpecList = [self indexForItem:item2 inList:specList];
return [#(indexForItemEquivalent1InSpecList) compare:#(indexForItemEquivalent2InSpecList)];
}];
NSLog(#"Sorted: %#", sorted);
With:
-(NSInteger)indexForItem:(Item *)item inList:(NSArray *)list
{
for (NSInteger i = 0; i < [list count]; i++)
{
if ([list[i][#"number"] integerValue] == [[item number] integerValue])
{
return i;
}
}
return NSIntegerMax; //If not found, we put it at the end of the list
}
Output:
Sorted: (
"<Item 0x146678f0> number: 2 serial: S02",
"<Item 0x14667e10> number: 4 serial: S04",
"<Item 0x14667900> number: 3 serial: S03",
"<Item 0x14654200> number: 1 serial: S01",
"<Item 0x14667e20> number: 5 serial: S05"
)
I override -description to make log clearer:
-(NSString *)description
{
return [NSString stringWithFormat:#"<%# %p> number: %# serial: %#", [self class], self, _number, _serailNumber];
}
In other words:
You have to find the index of the corresponding Item object inside specList (see indexForItem:inList:). I used integerValue because you are using #"002" and #"2", which aren't equal strings.
Then in the NSComparator you compare the two indexes.
For item1 and item5 which are at the end, I let them as if. There is no guarantee of their order since they are not present in specList. If you want to put them in "ascending" order, you have to do instead:
NSInteger indexForItem1InSpecList = [self indexForItem:item1 inList:specList];
NSInteger indexForItem2InSpecList = [self indexForItem:item2 inList:specList];
if (indexForItem1InSpecList == NSIntegerMax && indexForItem2InSpecList == NSIntegerMax)
{
return [#([[item1 number] integerValue]) compare:#([[item2 number] integerValue])];
}
else
{
return [#(indexForItem1InSpecList) compare:#(indexForItem2InSpecList)];
}
Here is an example of sorting second array referring to the first one:
NSArray *users = #[#"Dave",#"Mike",#"Joe",#"Jason",#"Kevin"];
NSArray *iqs = #[#110,#145,#75,#122,#130];
NSMutableArray *array = [NSMutableArray array];
for (int idx = 0;idx<[users count];idx++) {
NSDictionary *dict = #{#"Name": users[idx],#"IQ":iqs[idx]};
[array addObject:dict];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"IQ" ascending:NO];
[array sortUsingDescriptors:#[descriptor]];
Related
I need to show a grouped tableview from the below data. I need to categorise the below array based on "account_type".
For Eg: I need to show Table Section Heading "Savings" and list all savings type accounts, then similarly get Unique account types and gave that as section header and account numbers in table rows. I am able to get section headers using NSSet, but how to get row counts and display it in a UITableView.
<__NSArrayM 0x7f8ef1e8b790>(
{
"account_no" = 123;
"account_type" = Savings;
},
{
"account_no" = 123456;
"account_type" = Savings;
},
{
"account_no" = 00000316;
"account_type" = "DPN STAFF NON EMI";
},
{
"account_no" = 1000000552;
"account_type" = "DPN STAFF EMI LOANS";
})
I need to display the above data in UITableView like
section 0 --- Savings
Row 1 - 123
Row 2 - 123456
section 1 ---> DPN STAFF NON EMI
Row 1 - 00000316
Thanks,
AKC
You can make use of NSDictionary also. The below code worked perfectly.
if([arrySelectedDetails count] >0){
grouped = [[NSMutableDictionary alloc] initWithCapacity:arrySelectedAcctDetails.count];
for (NSDictionary *dict in arrySelectedDetails) {
id key = [dict valueForKey:#"type"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
typeArray= [[NSMutableArray alloc]init];
for(NSDictionary *groupId in arrySelectedDetails){
if(!([typeArray count]>0)){
[typeArray addObject:[groupId valueForKey:#"type"]];
}
else if (![typeArray containsObject:[groupId valueForKey:#"type"]]) {
[typeArray addObject:[groupId valueForKey:#"type"]];
}
}
}
Then for UITableView Delegates:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [typeArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [grouped[[typeArray objectAtIndex:section]] count]
}
Try the below code:
NSMutableArray *resultArray = [NSMutableArray new];
NSArray *groups = [arrySelectedAcctDetails valueForKeyPath:#"#distinctUnionOfObjects.account_type"];
NSLog(#"%#", groups);
for (NSString *groupId in groups)
{
NSMutableDictionary *entry = [NSMutableDictionary new];
[entry setObject:groupId forKey:#"account_type"];
NSArray *groupNames = [arrySelectedAcctDetails filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"account_type = %#", groupId]];
for (int i = 0; i < groupNames.count; i++)
{
NSString *name = [[groupNames objectAtIndex:i] objectForKey:#"account_no"];
[entry setObject:name forKey:[NSString stringWithFormat:#"account_no%d", i + 1]];
}
[resultArray addObject:entry];
}
NSLog(#"%#", resultArray);
Output:
{
"account_no1" = 00000316;
"account_type" = "DPN STAFF NON EMI";
},
{
"account_no1" = 123;
"account_no2" = 123456;
"account_type" = Savings;
},
I am having a response data as below .I have an array populated by dictionaries, and I need to sort last two values from each index of multi dimensional array.
This is my array:
arrayListstatus
(
{
"Applicant_FirstName" = "";
"Applicant_LastName" = "";
"Application_ID" = test;
"Application_Status" = "";
},
{
"Applicant_FirstName" = John;
"Applicant_LastName" = Doe;
"Application_ID" = 0002;
"Application_Status" = Recertify;
}
)
Here is my code:
- (NSArray *)subItems
{
NSMutableArray *items = [[NSMutableArray alloc] init];
for (int ar = 0; ar < arrayListstatus.count; ar++)
{
NSArray *thirdarray=[arrayListstatus objectAtIndex:ar] ;
NSLog(#"thirdarray %#",third array);
[items addObject:thirdarray];
}
NSLog(#"itemss %#",items);
return items;
}
i think this should do the trick:
- (NSArray *)subItems
{
NSMutableArray *items = [[NSMutableArray alloc] init];
for (int ar = 0; ar < arrayListstatus.count; ar++)
{
NSArray *thirdarray= [arrayListstatus objectAtIndex:ar] ;
NSMutableDictionary *tmpDict = [NSMutableDictionary alloc] init];
[tmpDict setObject:[thirdarray objectAtIndex:2] forKey:#"Application_ID"];
[tmpDict setObject:[thirdarray objectAtIndex:3] forKey:#"Application_Status"];
[items addObject:tmpDict];
[items addObject:tmpDict];
}
NSSortDescriptor *sortDescriptor;
sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:"Application_Status" ascending:YES], nil]];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [items sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"itemss %#",items);
return items;
}
NSArray*arr = #[#"ram",#"Ram",#"vinoth",#"kiran",#"kiran"];
NSSet* uniqueName = [[NSSet alloc]initWithArray:arr];
NSLog(#"Unique Names :%#",uniqueName);
Output:
but i need the output as
You could first convert them all to lowercase strings.
NSArray *arr = #[#"ram",#"Ram",#"vinoth",#"kiran",#"kiran"];
NSArray *lowerCaseArr = [arr valueForKey:#"lowercaseString"];
NSSet* uniqueName = [[NSSet alloc] initWithArray:lowerCaseArr];
NSLog(#"Unique Names :%#",uniqueName);
Unique Names :{(
ram,
kiran,
vinoth
)}
Try this:
NSArray *arr = [NSArray arrayWithObjects:#"Ram",#"ram", nil]; //this is your array
NSMutableArray *arr1 = [[NSMutableArray alloc]init]; //make a nsmutableArray
for (int i = 0; i<[arr count]; i++) {
[arr1 addObject:[[arr objectAtIndex:i]lowercaseString]];
}
NSSet *set = [NSSet setWithArray:(NSArray*)arr1];//this set has unique values
This will always preserve casing form that was existing in your original container (although it's undefined which casing):
NSArray<NSString*>* input = ...
NSMutableDictionary* tmp = [[NSMutableDictionary alloc] init];
for (NSString* s in input) {
[tmp setObject:s forKey:[s lowercaseString]];
}
return [tmp allValues];
Create a mutable array the same size as arr. Fill it with lowercaseString versions of each element of arr. Make the set out of that.
#Updated
Using this you remove uppercase string from your array.
NSMutableArray *arr= [[NSMutableArray alloc]initWithObjects:#"ram",#"Ram",#"vinoth",#"kiran", nil];
NSMutableArray *arrCopy = [[NSMutableArray alloc]init];
for (int index = 0 ; index<arr.count; index++) {
NSUInteger count = [[[[arr objectAtIndex:index] componentsSeparatedByCharactersInSet:[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]] componentsJoinedByString:#""] length];
if (count == 0) {
[arrCopy addObject:[arr objectAtIndex:index]];
}
}
NSLog(#"Print Mutable Copy %#",arrCopy);
try this one
NSArray *copyArray = [mainArray copy];
NSInteger index = [copyArray count] - 1;
for (id object in [copyArray reverseObjectEnumerator]) {
if ([mainArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[mainArray removeObjectAtIndex:index];
}
index--;
}
copyArray=nil;
I have a UITableView with custom cellView populated with an array (cf. functs) without section. My goal is to create a search bar (which is ok) with a list index (which is the problem).
After reading a lot of documentations, I plan to use these three methods: "numberOfSectionsInTableView", "sectionIndexTitlesForTableView" and "sectionForSectionIndexTitle"
How to create the NSDictionnary of functs array with the following structure?
//in viewDidLoad
// Initialize the functs array
Funct *funct1 = [Funct new];
funct1.name = #"AAA";
funct1.detail = #"detail1...";
funct1.image = #"a.jpg";
Funct *funct2 = [Funct new];
funct2.name = #"BBB";
funct2.prepTime = #"detail2...";
funct2.image = #"b.jpg";
functs = [NSArray arrayWithObjects:funct, funct2, nil]; //etc.
//For Index list: one section per letter
NSString *letters = #"a b c d e f g h i j k l m n o p q r s t u v w x y z";
self.indexTitlesArray = [letters componentsSeparatedByString:#" "];
Thanks in advance
Here you have a good tutorial with example project. It´s what you are looking for.
It´s an example for TableView indexed, but it has a good example for sections and rows
There is in this example this method very useful for you
static NSString *letters = #"abcdefghijklmnopqrstuvwxyz";
// This method returns an array of dictionaries where each key is a letter
// and each value is a group of words corresponding to the letter.
+ (NSArray *) wordsFromLetters {
NSMutableArray *content = [NSMutableArray new];
for (int i = 0; i < [letters length]; i++ ) {
NSMutableDictionary *row = [[[NSMutableDictionary alloc] init] autorelease];
char currentWord[WORD_LENGTH + 1];
NSMutableArray *words = [[[NSMutableArray alloc] init] autorelease];
for (int j = 0; j < WORD_LENGTH; j++ ) {
if (j == 0) {
currentWord[j] = toupper([letters characterAtIndex:i]);
}
else {
currentWord[j] = [letters characterAtIndex:i];
}
currentWord[j+1] = '\0';
[words addObject:[NSString stringWithCString:currentWord encoding:NSASCIIStringEncoding]];
}
char currentLetter[2] = { toupper([letters characterAtIndex:i]), '\0'};
[row setValue:[NSString stringWithCString:currentLetter encoding:NSASCIIStringEncoding]
forKey:#"headerTitle"];
[row setValue:words forKey:#"rowValues"];
[content addObject:row];
}
return content;
}
You can take the main idea from this resource, but if you prefer, I adapted the code. I think works fine
NSMutableArray *funcsArray = [NSMutableArray array];//Here you add all your functs objects
[funcsArray addObjects: funct1, funct2...];
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"name"
ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [funcsArray sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *funcsArrayOrdered = [NSMutableArray array];//Here you add all your functs objects
NSMutableArray *funcsIndexed = [NSMutableArray array];
NSMutableArray *letters = [NSMutableArray array];
NSString *currentLetter = nil;
int numItems = [funcsArrayOrdered count];
for (Funct *functObj in funcsArrayOrdered) {
NSLog(#"funct: %#", functObj.name);
numItems--;
NSString *string = userT.name;
if (string.length > 0) {
NSString *letter = [[string substringToIndex:1] uppercaseString];
if ([currentLetter length] == 0) {
currentLetter = letter;
}
if (![letter isEqualToString:currentLetter] || numItems == 0) {
if ([letter isEqualToString:currentLetter] && numItems == 0) {
[letters addObject:functObj];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:currentLetter forKey:#"headerTitle"];
[dic setValue:letters forKey:#"rowValues"];
[funcsIndexed addObject:dic];
letters = [NSMutableArray array];
}else{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:currentLetter forKey:#"headerTitle"];
[dic setValue:letters forKey:#"rowValues"];
[funcsIndexed addObject:dic];
letters = [NSMutableArray array];
[letters addObject:functObj];
currentLetter = letter;
if (numItems == 0 && [funcsArrayOrdered count] > 1) {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:currentLetter forKey:#"headerTitle"];
[dic setValue:letters forKey:#"rowValues"];
[funcsIndexed addObject:dic];
}
}
}else {
[letters addObject:functObj];
}
}
}
Now you will have your array of Dictionaries ordered in funcsIndexed
I want to compare 2 NSMutableArray and get different object into third Array. How can i do that ?
Array1 can loop object .
Array1 = "a", "b","c","d","a","b","c";
Array2 = "a", "b", "c";
And then result
Array3 = "d";
Thanks in advance
Use sets for set operations:
NSSet *set1 = [NSSet setWithArray:array1];
NSMutableSet *set2 = [NSMutableSet setWithArray:array2];
[set2 minusSet:set1];
You Can try this too.
NSMutableArray *array1 = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"1", nil];
NSMutableArray *array2 = [[NSMutableArray alloc]initWithObjects:#"2",#"1", nil];
NSMutableArray *largeArray;
NSMutableArray *shortArray;
if([array1 count] > [array2 count]){
largeArray = array1;
shortArray = array2;
} else {
largeArray = array2;
shortArray = array1;
}
[largeArray removeObjectsInArray:shortArray];
for (NSString *va in largeArray) {
NSLog(#"%#",va);
}
NSMutableArray *gotDiffArry= [[NSMutableArray alloc] init];
for(int i = 0 ; i < FirstArray.count; i++) {
if(i < seconArray.count){
if(![seconArray[i] isEqual:firstArray[i]]){
[gotDiffArry addObject:[NSNumber numberWithInt:i]];
}
} else {
[gotDiffArry addObject:[NSNumber numberWithInt:i]];
}
}
EDITED:
for (int i = 0 ; i < firstArray.count ; i ++)
{
NSString *search = [firstArray objectAtIndex:i];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF CONTAINS %#", search];
NSMutableArray *temAraay = [secondArray filteredArrayUsingPredicate: predicate];
if(temArray.count >=0 )
{
NSLog("%#", [temArray objectAtIndex:0]);
}
}
I have used the following and got the desired results:
for(int i =0; i<[arraytwo count]; i++)
{
if (![arrayone containsObject:[arraytwo objectAtIndex:i]])
[arraythree addObject: [arraytwo obectAtIndex:i]];
}
NSLog(#"%#",arraythree);