I want to create an algorithm but not sure how to start.
This algorithm will actually be a method that accepts an array of N objects with some of the attributes, createdAt, value.
I will sort the array from older to new (createdAt) and then I have to find out how consistent the available data is, meaning, for every one hour do I have at least 5 records, and for every half an hour 2 records.
Example-testcode:
- (void) normalizeData:(NSArray*)records
{
// sort the records
NSArray* sortedRecords = [records sortWithCreatedAt];
// split all dates in the records, distinct them, and create a dictionary with a key for every date, for value create another dictionary with the hour as key and the records as the value.
NSArray* distinctDates = [sortedRecords valueForKeyPath:#"#distinctUnionOfObjects.createdAt"]; // should only consider month-day-year-hour
NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
for (NSDate* date in distinctDates)
{
NSString* stringDate = [date string];
NSArray* recordsForDate = [sortedRecords valueForKeyPath:[NSString stringWithFormat:#"[collect].{createdAt=%#}.self", stringDate]]; // let's say you got them with this line
[dictionary setObject:recordsForDate forKey:date];
}
for (NSDate* keyDate in dictionary)
{
NSArray* records = [dictionary objectForKey:keyDate];
Record* previousRecord = nil;
for (Records* record in records)
{
// I'll have to keep the previous record and compare the time difference with the new
NSInteger secondsAfterDate = 0;
if (previousRecord)
{
secondsAfterDate = [record.createdAt timeIntervalSinceDate:previousRecord.createdAt];
// add logic to create trend difference in a model that has for every hour of the records count, the records and suffice description
// logic if the records count and timespan is suffice.
}
previousRecord = record;
}
}
}
I would appreciate any contribution to the process in the method.
Also the ultimate goal is to create a return (invoke a block handler) for every result of the records that processed.
The logic should end with, 5 records at least per hour and a timespan between them under 15 minutes.
Take the total length of time of record collection (difference between createdAt of first record and createdAt of last record) and discretize it into bins. Place each object in the appropriate bin. Then used a sliding window with two window sizes (30 minutes and 60 minutes). As you walk along the array, continually evaluate whether the conditions you describe are met.
Note that for the above approach it's important to properly define the bin width as the resolution of your timestamping process. Since you don't indicate this in your post, feel free to comment if this is a problem.
Related
I am using Realm database for iOS application where i have a use case in which i want to filter result set by distinct values for a particular field. This field is not a primary key of the realm table.
I was not able to construct query for that.
Sample query :
RLMResults *allFiles = [FileRLMObject objectsInRealm:realmObject where:#"colA == %#", #"test1"];
FileRLMObject is a subclass of RLMObject from realm library
here table contains one column with name colB. While getting allFiles results, i want to get rows which are having distinct colB values.
Any suggestions how i can achieve this?
Realm doesn't support distinct queries yet. You can subscribe issue #1103 to track progress on that.
As a workaround, you could query for all values for colB first and then select objects for each value of it, as seen below:
NSArray *values = [FileRLMObject.allObjects valueForKey:"type"];
NSSet *distinctValues = [NSSet setWithArray:values];
NSMutableArray *allFiles = [NSMutableArray new];
for (NSString *colB in distinctValues) {
// This takes the firstObject.
// You might want to modify the sort order to make sure
// you get a certain object in case that there may exist
// multiple objects per distinct value.
FileRLMObject *object = [FileRLMObject objectsWhere:#"colB == ?", colB].firstObject;
[allFiles appendObject:object];
}
I'm trying to perform the relatively simple task of deleting the items in an NSMutableArray that fit a certain criteria.
In this particular case, I'd like to delete the items where all of the following are true:
city: Seattle
state: WA
timestamp: more than 60 seconds old
An NSLog of my array looks like this:
array = (
{
city = "Seattle";
state = "WA";
timestamp = 1432844384;
},
{
city = "Dallas";
state ="TX";
timestamp = 1432844415;
},
{
city = "Seattle";
state = "WA";
timestamp = 1432845329;
}
)
I've tried using NSPredicate to filter the array, but I think that may be overcomplicating things. Any recommendations would be great! Thank you!
You could get the indexes of such elements by using indexesOfObjectsPassingTest: (see docs)
NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// check if obj is matching all your criteria
}
Then remove the items using removeObjectsAtIndexes: (see docs)
[array removeObjectsAtIndexes:indexes];
No, filtering out the items to delete and then deleting them is the right way. It iw not complicated, because obviously getting the specified items is filtering with a predicate + deleting them is deleting them. How could a solution be less complicated?
Maybe it is easier to you, to filter out the items not to delete. Simply add a NOT to your predicate.
Here your timestamp is unique every time. So you have delete data base on timestamp.
First you have to get index of that timestamp from that array.
NSInteger index = [[array valueForKey:#"timestamp"] indexOfObject:timestamp];
After getting this index of array you have to delete data from that index.
[array removeObjectAtIndex:index];
I have an string with an hour in it, for example "15:15", and an array of other hours in strings ex: #["15:00","16:00","17:00"] I should compare the single string with the array ones in order to get the ETA in a bus station, I tried this code but it keeps iterating and gives me the last greater value in the array, not the first greater value as I need.
int i = 0;
horaArribada = [[[objects objectAtIndex:0]objectForKey:#"Horaris"]objectAtIndex:i];
while ([hora compare:horaArribada]) {
i++;
if (i >= [[[objects objectAtIndex:0]objectForKey:#"Horaris"]count]) {
break;
}else{
horaArribada = [[[objects objectAtIndex:0]objectForKey:#"Horaris"]objectAtIndex:i];
}
}
self.tfHoraArribada.text = horaArribada;
}
}
Where objects is a query from Parse and hora the single string with an hour in it.
You appear to be doing a lot of extra work to iterate over your array. Instead, try a different format for your loop:
for (NSString *horaArribada in [[objects objectAtIndex:0] objectForKey:#"Horaris"]) {
if ([hora compare:horaArribada] == NSOrderedAscending) {
self.tfHoraArribada.text = horaArribada;
break;
}
}
This assumes that your Horaris array is already sorted such from smallest to largest. Also, the logic will not work for the midnight rollover, so you'll probably want to account for that.
I have a NSArray with objects Called Houses, each object has 3 fields = id,address,price
I can set the value by using
[house setValue:#"£100k" forKey:#"price"];
However I have another NSArray called Movements, each object has 2 fields, id & price
so how do I update the 1st array with details from the 2nd array.. in english it I trying to do "Update house price with movement price where house id = movement id"
Thanks in advance
Sounds like you want a double loop:
for (House* house in houses)
for (Movement* movement in movements)
{
if (house.id == movement.id)
house.price = movement.price
}
If there will only be one such instance you may want to break early, you'll need an extra BOOL for this:
BOOL breaking = false;
for (House* house in houses)
{
for (Movement* movement in movements)
{
if (house.id == movement.id)
{
house.price = movement.price
breaking = true;
break;
}
}
if (breaking) break;
}
Edit: If you are doing this kind of thing frequently, you probably want to construct a dictionary keyed on the id field so you can look up an object quickly rather than by looping the whole array. NSDictionary is the class you want for this, also note that keys must be objects, so if your id field is an int you'll want to convert it to an NSNumber with [NSNumber numberWithInt:] before using it as a key.
I need to scroll through several thousands of words to categorize them... to determine which words have the same pattern. (this part works)
For example, a four letter word that has two m's in 2nd & 4th position represent a pattern ("-m-m"). Once I have gone through all the words, I will know how many words there are for any given pattern. I am scrolling through now, but the problem I have is 'remembering' how many words I have in any given pattern.
I was thinking of using NSMutableDictionary and have the key be the pattern ('-m-m-') and the object represent the count of that pattern. This means every time I come across a pattern, I look up that pattern in the dictionary, get the key, increment the key, and put it back in the dictionary.
I need help with both the decision and syntax for performing this task.
Thank You
The answer to your question was this part of your (given) question "I will know how many words there are for any given pattern.". I would use an array of dictionary. You use the dictionary to store key value pair: a known pattern and the count. And you use the array to store those KVP records. So the next time you detect a pattern, search for the array for that record (dictionary), if found, increment the count. If not, create new record and set the count to 1.
Added sample code:
#define kPattern #"Pattern"
#define kPatternCount #"PatternCount"
-(NSMutableDictionary *)createANewDictionaryRecord:(NSString *) newPattern
{
int count = 1;
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
newPattern, kPattern,
[NSString stringWithFormat:#"%i",count], kPatternCount,
nil];
return myDictionary;
}
-(void)addANewPatternToArray:(NSMutableDictionary *)newDictionary
{
// NSMutableArray *myArrayOfDictionary = [[NSMutableArray alloc]init]; // you need to define it somewhere else and use property etc.
[self.myArrayOfDictionary addObject:newDictionary]; //or [self.myArrayOfDictionary addObject:newDictionary]; if you follow the recommendation above.
}
-(BOOL)existingPatternLookup:(NSString *)pattern
{
for (NSMutableDictionary *obj in self.myArrayOfDictionary)
{
if ([[obj objectForKey:kPattern] isEqual:pattern])
{
int count = [[obj objectForKey:kPatternCount] intValue] + 1;
[obj setValue:[NSString stringWithFormat:#"%i",count] forKey:kPatternCount];
return YES;
}
}
[self.myArrayOfDictionary addObject:[self createANewDictionaryRecord:pattern]];
return NO;
}
-(void)testData
{
NSMutableDictionary *newDict = [self createANewDictionaryRecord:#"mmm"];
[self addANewPatternToArray:newDict];
}
-(void) printArray
{
for (NSMutableDictionary * obj in self.myArrayOfDictionary)
{
NSLog(#"mydictionary: %#", obj);
}
}
- (IBAction)buttonPressed:(id)sender
{
if ([self existingPatternLookup:#"abc"])
{
[self printArray];
} else
{
[self printArray];
}
}
Not being an objective C expert but solving this problem in java before, I would say a dictionary(I used a map when doing it in java) is the best way. Check if the key(pattern) already exist if so increment that count else put a new one in the dictionary.
EDIT
If you want to not just get the count of a pattern, but in fact tell which words fall under that pattern, I would use a dictionary of strings to mutable arrays. In the arrays you store the words and the key to the array is the pattern(as a string), similar code as above but instead of just incrementing the count, you have to add the new word to the array.
The only difference in NSDictionary and NSMutableDictionary is that one can have objects added to it. I think your implementation is good, but English is a complex language. It would be more efficient to parse out the string with regex than to set a key for it.
Why don't you use NSCountedSet instead:
NSCountedSet Class Reference
..which is available in iOS 2.0 and later?
Each distinct object inserted into an NSCountedSet object has a counter associated with it. NSCountedSetkeeps track of the number of times objects are inserted [...] Thus, there is only one instance of an object in an NSSet object even if the object has been added to the set multiple times. The count method defined by the superclass NSSet has special significance; it returns the number of distinct objects, not the total number of times objects are represented in the set.
Then use:
- (NSUInteger)countForObject:(id)anObject
Use a dictionary of NSMutableArrays, and check for the existence of each search key as you recommended. If the key doesn't exist, add an NSMutableSet or NSMutableArray (depending on your needs) for the searched key type "-m-m" for example, and then add to the set or array for that key.