R.Ham R.Ham - 2 months ago 10
Swift Question

Swift: Multi item for loop to check input values in an array

I am trying to create a multi item for statement to test two values of an array. I have an array of type NSDate, with multiple dates saved from core data. I am aiming to take the dates from the array, and add them to a new array if the dates are on a unique day. I want to check the items in an array and if they have the same Day then not add them to a new array.

Currently I have been using calendar.components.Day to check if two dates have the same value, but it is not returning the correct answer:

func consecutiveDatesCheck(dateArray: [NSDate]) -> Int {

// The incoming parameter dateArray is immutable, so first make it mutable
var mutableArray = dateArray

// Next, sort the incoming array
mutableArray.sortInPlace({ $0.compare($1) == NSComparisonResult.OrderedAscending })

var x = 0
var numberOfConsecutiveDays = 1
var streakArray = [Int]()
var notSameDays = [NSDate]()

// Cycle through the array, comparing the x and x + 1 elements
while x + 1 < mutableArray.count {

let calendar: NSCalendar = NSCalendar.currentCalendar()
let components = calendar.components(.Day, fromDate: mutableArray[x], toDate: mutableArray[x + 1], options: [])

// If the difference between the dates is greater than 1, append the streak to streakArray and reset the counter
if abs(components.day) = 0 {
streakArray.append(numberOfConsecutiveDays)
numberOfConsecutiveDays = 1
}

// If the difference between the days is exactly 1, add one to the current streak
else if abs(components.day) == 1 {
numberOfConsecutiveDays += 1
}

x += 1
}

// Append the final streak to streakArray
streakArray.append(numberOfConsecutiveDays)
print(streakArray)

// Return the user's longest streak
return streakArray.maxElement()!
} /*


My current data in dateArray:

2016-08-20 06:38:23 +0000
2016-08-20 06:43:59 +0000
2016-08-20 06:49:19 +0000
2016-08-20 06:58:59 +0000
2016-08-20 07:05:44 +0000
2016-08-20 09:05:25 +0000
2016-09-02 12:05:55 +0000
2016-09-02 17:39:01 +0000
2016-09-03 13:37:31 +0000
2016-09-03 13:41:10 +0000
2016-09-03 13:59:36 +0000
2016-09-03 14:26:11 +0000
2016-09-03 14:48:57 +0000
2016-09-03 14:51:25 +0000
2016-09-03 15:06:56 +0000
2016-09-03 15:15:00 +0000
2016-09-04 13:53:48 +0000
2016-09-04 13:56:13 +0000
2016-09-04 14:16:29 +0000
2016-09-04 17:33:16 +0000
2016-09-05 16:53:32 +0000
2016-09-06 12:20:16 +0000
2016-09-06 15:19:14 +0000
2016-09-06 15:27:07 +0000
2016-09-06 15:30:48 +0000
2016-09-06 15:32:14 +0000
2016-09-06 15:39:34 +0000
2016-09-06 15:53:15 +0000
2016-09-06 16:08:45 +0000
2016-09-06 16:21:15 +0000
2016-09-06 17:41:09 +0000
2016-09-10 13:04:11 +0000

Answer

Edit: I'm not 100% clear on your requirements. I think what you want is the number of consecutive days, ending in the current day, for which you have measurements data. Updated my answer below.

func consecutiveDatesCheck(dateArray: [NSDate]) -> Int {
    let calendar = NSCalendar.currentCalendar()
    let uniqueDates = NSSet(array: dateArray.map { calendar.startOfDayForDate($0) }).sort {
        $0.timeIntervalSince1970 > $1.timeIntervalSince1970
    } as! [NSDate]

    var lastDate = calendar.startOfDayForDate(NSDate())
    var i = 0

    while i < uniqueDates.count && uniqueDates[i].compare(lastDate) == .OrderedSame {
        lastDate = calendar.dateByAddingUnit(.Day, value: -1, toDate: lastDate, options: [])!
        i += 1
    }

    return i
}