Getting Max Date from NSArray, KVC - ios

I've got an array of NSDates and I'd like to grab the largest NSDate from the array. While i could always sort them and grab the first/last, is there a way to do this with KeyValueCoding or some other quick one liner kind of way? I know that I could use something like valueForKeyPath#"#max.date" if the objects had a date property, but what if the objects are dates themselves??
thanks

You can use,
NSDate *maxDate = [dateArray valueForKeyPath:#"#max.self"];
This will give you the largest date from array. You dont have to sort the array before doing this.
From the documentation,
The #max operator compares the values of the property specified by the
key path to the right of the operator and returns the maximum value
found. The maximum value is determined using the compare: method of
the objects at the specified key path. The compared property objects
must support comparison with each other. If the value of the right
side of the key path is nil, it is ignored.
Note that #max will do compare: and then will find out the max value.

Agree with #SeanDanzeiser. To be more specific, here's a ~70 byte one-liner:
// if dateArray is the array of dates ...
NSDate *maxDate = [[dateArray sortedArrayUsingSelector:#selector(compare:)] lastObject];

Related

(Swift 3) Trying to sort an array of class objects by Date in swift 3?

I have an array of objects that has a member that is type Date, and I'm trying to sort the whole array by Date, and it's not sorting correctly.
This is the code I'm using, the name of the array is alarms and the name of the member type Date is time.
alarms.sort(by: { $0.time.compare($1.time) == .orderedAscending })
and whenever I sort it it just doesn't work correctly, and I'm testing it by printing all the values in a for loop.
Can someone help me with the syntax for this?
The compare is a NSDate function. With Date you can just use < operator. For example:
alarms.sort { $0.time < $1.time }
Having said that, compare should work, too, though. I suspect there's some deeper issue here, that perhaps your time values have different dates. You might only be looking at the time portion, but when comparing Date objects, it considers both the date and time. If you only want to look at the time portion, there are several ways of doing that, for example, look at the time interval between time and the start of the day:
let calendar = Calendar.current
alarms.sort {
let elapsed0 = $0.time.timeIntervalSince(calendar.startOfDay(for: $0.time))
let elapsed1 = $1.time.timeIntervalSince(calendar.startOfDay(for: $1.time))
return elapsed0 < elapsed1
}
There are lots of ways to do this, but hopefully this illustrates the idea.

Substring specific integer from string

I have google some related questions, but unfortunately didn't find answer.
I have string like 2016-07-22, i need to get an integer 07, evaluate it to 7 and save.
Of course, this is date, therefore it will change every time, so i cant suppose that year always will be 2016. I need to get string after 5th symbol up to 8th.
Is there any easy way to achieve that? Thanks.
If it's always that section of the string, you can use NSMakeRange(5, 2) and substringWithRange to pick out the month.
After you have "07", conversion is just a case of asking the string for its integerValue.
The "save" part depends entirely on where you want to save it.
Here is just one way (I can think of at least 3 other ways):
NSString *str = #"2016-07-22";
NSArray *elements = [str componentsSeparatedByString:#"-"];
NSAssert([elements count] == 3, #"Ahhh!");
NSInteger month = [elements[1] integerValue];

NSFetchRequest search for all objects from last Nth date

My data looks like:
objA date1 objnumber2
objB date2 objnumber1
objC date2 objnumber4
objD date2 objnumber3
objE date1 objnumber7
objF date3 objnumber6
objG date1 objnumber5
I am looking for all the objects which are from the Nth last date. The result objects need to be sorted using objnumber (this should be easy using NSSortDescriptor).
So if I specify N=1 (most recent date), I should get [objF] only. (date3 is most recent)
If N=3 (oldest date), I should get sorted [objA, objG, objF]
The sorting part is easy.
My question is do I really need to firstly search for the latest date (using combination of sortdescriptor and nsfetchrequest searchLimit) in the entire data? Then do a second search to find all objects from that date (using nspredicate) and sort it?
Or is there a better way to perform this type of search? How would you generalize this for Nth date instead of last date? That would be a big performance hit no??
NOTE that the date is not known beforehand.
Edit2: okay this is even more complicated since I am using NSDate. So pretty much all the objects have unique dates lol. Gotta throw nsdateformatter in there in the mix too :(
I figured out a solution to my problem.
Instead of using the date, I added a new Int64 NSNumber attribute. Everyday the obj is added, all the objects are tagged with that number for that particular day.
For retriving all objects from Nth day, I firstly do a "fetchlimit 1" nsfetchrequest for that number in a sorted fetchrequest. That gives me the last number.
Now for the Nth last objects, I subtract N from the last number. Then I perform a "nspredicted" nsfetchrequest for all objects with that number attribute. Then I simply just sort the result array.
This resolves my question :D

Simple convert NSString with comma to float or double.

I have a screen where the user can enter some information. It shows a decimalPad. According to the user locale, I know the decimalPadwill show commaor period, or even something else.
Therefore, my database will contain NSStrings stored from the users, although, some of them will have comma, like 5,4, or period, as in 5.4. The problem is that I need to do some math with these values, and I can't find a pattern to convert them.
Lets say the NSStringhas a comma, as in 5,4. I can easily convert that to a floatusing:
NSNumberFormatter *commas = [NSNumberFormatter new];
commas.numberStyle = NSNumberFormatterDecimalStyle;
NSLocale *commaLocale = [[NSLocale alloc] initWithLocaleIdentifier: #"br_PT"];
commas.locale = commaLocale;
NSString *string = #"5,4";
float testFloat = [[commas numberFromString:string] floatValue];
I correctly get the result 5.4, and can go on with my math calculations. But for instance, if the number was saved by an US user, the NSString would be 5.4, and I wouldn't get the right result using this code. Even if I get user current locale, it doesn't help me, since the user will get values stored all around.
Anyway, I'm a little confused with this. How could I simply create a pattern to deal with this?
I don't want to work with the string, as in stringByReplacingOccurences..., anyway, at least if I can avoid that.
If you want to use the value as a number, you should store the value as a number in your database. NSNumber is a perfect object for that and with your method you can get correct value. When you show the value again to the user you should convert the NSNumber again with NSNumberFormatter. Everything else will be a workaround and have negative impact. Even with stringByReplacingOccurences... you have the risk that somebody uses thousand-dots or commas...

grouping objects by date (ios NSDate)

Now I have a 1-dimonsion NSArray, each element of which is a NSMangedObject with a NSDate Attribute,
for example
an event Entity has an date(NSDate) attribute and name(NSString) attribute.
So the initilized array should be like this:
(NSArray) Events: event1, event2, event3,...,nil
Now, I need to group these objects by their date so that I can make this array the data source of a sectioned tableView.
And I just need the elememts in a same section have the same date, here the date means year,month,day, and with no hour or minute.
So the grouped NSArray should be a 2-dimension array, such as:
(NSArray) Events: day1, day2, day3, day4,...,nil;
and here day1,day2... are also a NSArray, and inside of them are really event objects. like this:
(NSArray) day1: event1, event2, event3, ..., nil;
So how can I realize this ?
I guess I can not use NSFetchedResultsController, since actually I have to fetch several entities, each of which has a NSDate attribute, and put them together to be grouped by date.
and I believe there's no problems about fetching,
I jus wonder how can I transfer the fetched 1-dimension array into the date-based 2-dimension array that I need?
Hoping someone to help and thanks very very much for answering!
You can use a custom NSValueTransformer to convert your entities' dates to ranges (or days). From there, you can use bindings with that if you like.

Resources