Swift: проверить, совпадает ли дата с любым днем ​​в массиве дат? - PullRequest
0 голосов
/ 28 мая 2018

У меня есть массив объектов date - записей.И я чередую месяц.Для каждого дня я хочу проверить, находится ли какая-либо дата в массиве в один и тот же день.Пока у меня есть это:

var date = month?.startOfMonth()
var end = month?.endOfMonth()
while date! <= end! {
   if posts.reduce(false,{Calendar.current.isDate(date, inSameDayAsDate: post.timeStamp)}) == true {
      ....
   }
   date = Calendar.current.date(byAdding: .day, value: 1, to: date!)

}

Я считаю, что это начинается с false и для каждого дня в сообщениях проверяет, совпадает ли это с одним и тем же днем, и если это так, превращает результат в true.Однако я думаю, что он также изменит его обратно на ложь в следующий раз, когда встретит ложное значение ...

То, что я хочу, это то, что возвращает истину, если любая из дат в постах совпадает с какой-то днем, а непоследний.Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

[Обновлено] Как уже правильно сказано, вам может быть более интересно иметь Set дней, в которых есть хотя бы один пост, что-то вроде:

let dayComponents: Set<Calendar.Component> = [.day, .month, .year, .era]
let calendar = Calendar.current

let daysWithPosts = Set(posts.map { post in
        calendar.dateComponents(dayComponents, from: post.date)
    })

Тогдадля каждого date вы можете проверить, находится ли он в этом наборе (контекст не изменился, обратите внимание на развертывание силы):

while date! <= end! {
    let currentDayComponents = calendar.dateComponents(dayComponents, from: date)
    let postsFound = daysWithPosts.contains(currentDayComponents)
    // <use postsFound as needed>
    date = Calendar.current.date(byAdding: .day, value: 1, to: date!)
}

Оригинальный ответ, адаптированный для нескольких дат:

Это должно сказать, есть ли сообщения в день указанной даты:

func areTherePosts(in posts: [Post], fromSameDayAs date: Date) -> Bool {
    let calendar = Calendar.current
    let dayComponents: Set<Calendar.Component> = [.day, .month, .year, .era]
    let specificDateComponents = calendar.dateComponents(dayComponents, from: date)

    return posts.contains { post in
        calendar.dateComponents(dayComponents, from: post.date) == specificDateComponents
    }
}

Использование в вашем контексте (опять же, без изменений):

while date! <= end! {
    let postsFound = areTherePosts(in: posts, fromSameDayAs: date!)
    // <use postsFound as needed>
    date = Calendar.current.date(byAdding: .day, value: 1, to: date!)
}
0 голосов
/ 28 мая 2018

Я в основном строю представление стека - для каждого дня - я создаю прямоугольник синего цвета, если в этот день есть пост, и очищаю, если нет.Таким образом, мне, наверное, нужно знать день.Однако фильтрация массива для элементов, находящихся в указанном месяце, кажется интересной.Вы можете показать, как это сделать?Возможно, я мог бы указать расположение только этих дней, а затем заполнить оставшуюся часть stackArray чистыми значениями, используя insertItem atIndex

По сути, я мог бы начать с двух функций, одной для фильтрации дат по месяцам иодин для фильтрации по дням.Причина, по которой я бы это сделал, в вашем случае - вы за каждый день, вы не хотите перефильтровать все доступные даты за месяц (но это только я)

func dates(_ dates: [Date], withinMonth month: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.month]
    let filtered = dates.filter { (date) -> Bool in
        calendar.dateComponents(components, from: date).month == month
    }
    return filtered
}

func dates(_ dates: [Date], forDay day: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.day]
    let filtered = dates.filter { (date) -> Bool in
        calendar.dateComponents(components, from: date).day == day
    }
    return filtered
}

Вы можете использоватьcontains подход, соответствующий как месяцу, так и дню, но, опять же, необходимо учитывать дополнительные издержкиВ приведенном выше примере вы можете просто проверить, содержится ли день в отфильтрованных датах по месяцам, что может быть ближе к желаемому результату

nb Это не так эффективнокак что-то вроде first или contains, так как это будет выполнять итерацию всего массива, находя каждый соответствующий элемент, но имеет приятный побочный эффект, предоставляя вам больше информации.Например, вы можете отсортировать полученные фильтры и просто выполнить итерации с начала месяца до конца, отсекая каждый день матча по мере его появления, как идею

Мысли вслух ...

Другим подходом может быть фильтрация доступных дат по месяцам, как указано выше, но затем для сопоставления результата с Set днями (т. Е. Int), это позволит вам либо выполнять итерацию по каждому днюмесяц и используйте contains(day), чтобы выполнить простую проверку, чтобы увидеть, содержится ли день.

Точно так же вы можете сопоставить представления с каждым днем ​​и повторять Set, изменяя состояние каждогоview.

Все зависит от того, какой контекст доступен больше, чем доступно, но, разумеется, существует множество способов решения этой проблемы

0 голосов
/ 28 мая 2018

Ваш текущий код в основном в порядке, хотя я бы заменил reduce на contains.

if let start = month?.startOfMonth(), let end = month?.endOfMonth() {
    var date = start
    var found = false
    while !found && date <= end {
        if posts.contains { Calendar.current.isDate(date, inSameDayAs: $0.timeStamp) } {
            found = true
        }
        date = Calendar.current.date(byAdding: .day, value: 1, to: date)
    }

    if found {
        // We have a match
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...