iOS Select specific entries to display in table - ios

I have an array, which contains multiple dictionaries.
Formatted like this:-
Array
- Index
- DOW = Weekday
- Index
- DOW = Weekend
- Index
- DOW = Weekday
I want to populate a table with data from only those dictionaries containing DOW = Weekday.
What is the quickest way of enumerating this?
Note that the data will be changed via filters, and then table reloaded.

You can filter your array using NSPredicate, like this:
NSArray *data = #[
#{#"Dow":#"Weekday", #"One":#"Two"} // Item 0
, #{#"Dow":#"Weekend", #"Three":#"Four"} // Item 1
, #{#"Dow":#"Weekday", #"Five":#"Six"} // Item 2
];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(Dow=='Weekday')"];
NSArray *res = [data filteredArrayUsingPredicate:pred];
The code above will keep NSArrays items 0 and 2, and remove item 1, because it does not contain an entry where #"Dow" is set to #"Weekday".
The data variable above represents the pre-filtered data in your example.

I'd suggest you read Apple UITableViewDataSource protocol guide here and perhaps this tutorial too.
Basically you'll want to -
Override numberOfSectionsInTableView: and return the number of sections in your table (0 if it's not relevant).
Ovveride tableView:numberOfRowsInSection: and here you can "apply" the needed filters on your dictionary and return the correct number of rows you actually want to display.
Next time you update the filters and call reloadTable again the above steps will filter the table correctly according to the new filters.

Related

Make arrays from excluding strings

I have 2 array of strings, lets say for simplicity it will be Array 1 - #[#"a",#"b",#"c"] and Array 2 will be - #[#"b",#"c", #"d"].
What i want is, to create an array from strings (yes, there will be strings, sometimes long enough, i put characters just for simplicity) that exclude strings contained in previous array. And second array, that otherwise, contain string that exist in first array and not exist in second.
So, with array i privded, it would be :
resultArray1 = #[#"d] (exist in second array, but not in first)
resultArray2 = #[#"a"] (exist in first array, but not in second)
How to enumerate through this arrays to get what i want to? Thanks.
Make a NSMutableArray from the array with the items you want to keep, and call removeObjectsInArray: on it:
NSMutableArray res1 = [arr1 mutableCopy];
[res1 removeObjectsInArray:arr2];
NSMutableArray res2 = [arr2 mutableCopy];
[res2 removeObjectsInArray:arr1];

Dont add NSMutabledictionary values in alphabetical order

I am trying to add datas to a dictionary using key value array but the dictionary values are arranged based on keys alphabetical order
my values and keys array contains :
myValueArray ={[orange,apple],
[ford,toyota,lexus]}
myKeyArray ={[fruits],[cars]}
I am adding keys and value to a NSMutabledictionary using
myDictionary = [[NSMutableDictionary alloc]initWithObjects:myValueArray forKeys:MainDelegate.myKeyArray];
myDictionary should be
myDictionary = { Fruits =(orange,apple);
cars =(ford,toyota,lexus);}
but it is added in key's alphabetical order and looks like
myDictionary = { cars =(ford,toyota,lexus);
Fruits =(orange,apple);}
is there a way to add key value pairs in dictionary as it is without any ordering.
I am trying this to populate a grouped uitableview. since keys are used as sections everything looks like contacts app where sections and its corresponding values are arranged alphabetically. But i need the recent section to be shown first(the first one in array).
If you need to conserve your initial order, then you have to use an NSMutableArray.
NSMutableDictionary is designed to be able to access the values for key in the fastest possible way, and having the key sorted helps with that.
Here is how to declare the dictionary and array and how to use them for a grouped tableView:
NSDictionary *myDictionary = #{ #"cars": #[#"ford" , #"toyota", #"lexus"], #"Fruits": #[#"orange", #"apple"]};
NSArray *keysArray = #[ #"Fruits", #"cars"];
// first section
NSString *sectionName = keysArray[0];
NSArray *sectionArray = myDictionary[sectionName];
// second section
sectionName = keysArray[1];
sectionArray = myDictionary[sectionName];
NSMutableDictionary doesn't have any sorting associated to it, when you print this in log, it will display in sorting order.
You can manage a separate NSMutableArray and put you key in the order in which you want to fetch from NSMutableDictionary.
That can be the easiest way to store values and fetch as per your requirement.
May this help you.

Passing array of objects to dynamic cells in Table view

I have used a Table View with Dynamic Prototype cells.
I have created a sample row in the table view with four values of a quantity:
Title
Min Value
Max Value
Current value.
I have created Table view controller and table view cell classes for accessing those properties in my code.
Now I have to set the values dynamically. I can see people suggesting to pass array of values separately for each.
Like:
Array 1 for Title : which will display title for all items in the row
Array 2 for Min value and so on.....
Is there a way that we pass an array of objects to the table view and it creates the table.
Please suggest.
I can see people suggesting to pass array of values separately for each.
Don't do this it is very poor approach, instead create a single array of NSDictionnaries, for instance:
_listOfValue =
#[
#{#"Title":#"title 1", #"Min Value":#"0", #"Max Value":#"100", #"Current value":#"50"},
#{#"Title":#"title 2", #"Min Value":#"4", #"Max Value":#"90", #"Current value":#"60"},
#{#"Title":#"title 3", #"Min Value":#"6", #"Max Value":#"70", #"Current value":#"70"}
];
This will make it easy to retrieve the data you need since they are not separated.
In numberOfRowsInSection you can return [self.listOfValue count].
In cellForRowAtIndexPath or didSelectRowAtIndexPath you can easily get the dictionnary at the IndexPath then parse the value of each key.
//Get the specific value
NSDictionnary *valueDict = _listOfValue[indexPath.row];
//read data from value dictionary
valueDict[#"Title"];
//or the old syntax
[valueDict objectForKey:#"Title"];
No, you can't pass the array direct to the table. Your table view controller would usually maintain the array (often a single array containing dictionaries or custom class instances) and your code in the table view controller uses that array to configure the cells.

Objective-C how to pull several random items out of NSArray without getting duplicates? [duplicate]

This question already has answers here:
Getting a random object from NSArray without duplication
(3 answers)
Closed 7 years ago.
I have an array of random properties I would like to assign to equipment within the game I'm developing.
The code that I use below is returning an NSArray. I'm interested if there's way to get item indices from that array without getting duplicate values. The obvious solution is to create a mutable array with the returned array, do random, remove item that was returned and loop until the number of items is received.
But is there a different way of getting X random items from NSArray without getting duplicates?
//get possible enchantments
NSPredicate *p = [NSPredicate predicateWithFormat:#"type = %i AND grade >= %i", kEnchantmentArmor,armor.grade];
NSArray* possibleEnchantments = [[EquipmentGenerator allEnchantmentDictionary] objectForKey:#"enchantments"];
//get only applicable enchantments
NSArray *validEnchantments = [possibleEnchantments filteredArrayUsingPredicate:p];
NSMutableArray* mutableArray = [NSMutableArray arrayWithArray:validEnchantments];
NSDictionary* enchantment = nil;
if(mutableArray.count>0)
{
//got enchantments, assign number and intensity based on grade
for (int i = 0; i<3;i++)
{
enchantment = mutableArray[arc4random()%mutableArray.count];
[mutableArray removeObject:enchantment];
//create enchantment from dictionary and assign to item.
}
}
You can shuffle the array using one of the following techniques:
What's the Best Way to Shuffle an NSMutableArray?
Non repeating random numbers
Then, take the first X elements from the array.
Many years ago, I was working on card game and I realized that shuffling the deck was an inefficient way to get random cards. What I would do in your shoes is pick a random element, and then replace it with the element at the end of the array, like so:
#interface NSMutableArray (pickAndShrink)
- (id) pullElementFromIndex:(int) index // pass in your random value here
{
id pickedItem = [self elementAtIndex:index];
[self replaceObjectAtIndex:index withObject:[self lastObject]];
[self removeLastObject];
return pickedItem;
}
#end
The array will shrink by one every time you pull an element this way.
You could use a random number generator to pick a starting index, and then pick the subsequent indices based on some kind of math function. You would still need to loop depending on how many properties you want.
Eg:
-(NSMutableArray*)getRandomPropertiesFromArray:(NSArray*)myArray
{
int lengthOfMyArray = myArray.count;
int startingIndex = arc4random()%lengthOfMyArray;
NSMutableArray *finalArray = [[NSMutableArray alloc]init]autorelease];
for(int i=0; i<numberOfPropertiesRequired; i++)
{
int index = [self computeIndex:i usingStartingIndex:startingIndex origninalArray:myArray];
[finalArray addObject:[myArray objectAtIndex:index]];
}
return finalArray;
}
-(int)computeIndex:(int)index usingStartingIndex:(int)startingIndex
{
//You write your custom function here. This is just an example.
//You will have to write some code to make use you don't pick an Index greater than the length of your array.
int computedIndex = startingIndex + index*2;
return startingIndex;
}
EDIT: Even your computeIndex function could use randomness in picking the subsequent indices. Since you have a startingIndex, and another index, you could use that to offset your function so that you never pick a duplicate.
EDIT: If your array is very large, and the subset you need to pick is small, then rather than shuffle the entire array (maybe more expensive), you could use this method to pick the number of items you need. But if your array is small, or if the number of items you need to pick are almost the size of the array, then the godel9's solution is better.
You can use a mutable array and then remove them as the are selected, use something like random()%array.count to get a random index. If you don't want to modify the array then copy it with [array mutableCopy].

Ordering objects under sections

Below is a screenshot of a UITableView that I want to order into by month. Currently their ordered by the first letter of the sub-heading in alphabetical order, what code should I use to make the events ordered into months? (By the way I have worked out how to order the sections)
Any help appreciated,
Seb
The best solution depends on what your data model looks like. Probably the simplest and most efficient, assuming your data model does not change very frequently, is just to have a routine that sorts each section's data in the order you want (based on each item's date). Create a list of pointers (or indices, again depending on your data structure's details), then all you have to do is look up the row index in the section's sorted index structure and display that element's data in your cellForRowAtIndexPath.
To optimize, you can keep a boolean "sorted" field in your data structure that is set to false whenever the data mutates in the table, then only sort on demand in the cellForRowAtIndexPath and set "sorted" to true.
EDIT: request for more step-by-step detailed description
OK, here's a bit more detail on how I'd go about it, assuming each of your sections is stored unsorted in a sortable container like NSMutableArray. Again the best solution depends on the details of your app like how frequently the section entries update and how you organize your data, and is there an upper bound on the number of entries in a section, etc. This is slightly different from my original suggestion in that the section's data container is directly sorted, and doesn't use an external ordering index.
Add a NSMutableSet sortedSections member somewhere convenient, close to your data model (inside its class would be best if you define it in a class)
// a section number is sorted if and only if its number is in the set
NSMutableSet *sortedSections;
When entries in sections are changed, added, or deleted, mark that section as unsorted by removing its number from the set
// just added, deleted, or changed a section entry entry
unsigned int sectionNum; // this section changed
...
NSNumber *nsNum = [NSNumber numberWithUnsignedInt:sectionNum];
[obj.sortedSections removeObject:nsNum];
In your cellForRowAtIndexPath (this may not be the most optimal place for this check, but it is a fast check and is the easiest location to get the sorting working), check if the section is sorted.
unsigned int sectionNum = [indexPath section];
NSNumber *nsNum = [NSNumber numberWithUnsignedInt:sectionNum];
if ( [obj.sortedSections containsObject:nsNum] )
// already sorted, nothing to do
else
{
// section needs to be resorted and reloaded
[mySectionData sortUsingFunction:compareSectionEntriesByDate context:nil];
// mark the section as sorted now
[obj.sortedSections addObject:nsNum];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
}
Here is an example sorting function, assuming your entry structures are of type NSDictionary and that you store the dates as NSDate objects with the key constant kEntryNSDate (which you would define yourself)
// sort compare function for two section entries based on date
//
static int compareSectionEntriesByDate( id e1, id e2, void *context)
{
NSDictionary *eDict1 = (NSDictionary *) e1;
NSDictionary *eDict2 = (NSDictionary *) e2;
NSDate *date1 = [eDict1 objectForKey:kEntryNSDate];
NSDate *date2 = [eDict2 objectForKey:kEntryNSDate];
int rv = [date1 compare:date2];
return rv;
}
That should be enough detail to get you going, good luck!

Resources