Swift - группировка массива товаров по неделям в течение большого периода времени - PullRequest
0 голосов
/ 31 января 2019

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

Я хочу достичь массива или словаря всех дат, сгруппированных по каждой отдельной неделе, и суммы всех сумм.в этой группе.

Я уже пытался сгруппировать их по .weekOfYear, однако это не учитывает сам год, и если бы эти две даты были на расстоянии более года, я бы всегдаесть только массив длиной 52 записи.

Я также изучил использование порядкового номера недели с помощью Calendar.current.ordinality(of: .weekOfYear, in: .era, for: 'date'), но он преобразуется в целое число, и я не уверен, как потом вернуть его обратнона дату

Ниже приведена копия моего кода, который я использую на игровой площадке xCode, и его вывод

import Foundation

let cal = Calendar.current

extension Date {
    var year: Int {
        return cal.component(.year, from: self)
    }
    var week: Int {
        return cal.component(.weekOfYear, from: self)
    }
    var weekAndYear: DateComponents {
        return cal.dateComponents([.weekOfYear, .year], from: self)
    }
}

struct Item {
    var date: Date
    var amount: Double
}

let startDate: Date = cal.date(from: DateComponents(year: 2018, month: 12, day: 2))!
let endDate: Date = cal.date(from: DateComponents(year: 2019, month: 1, day: 28))!

// Here I'm creating dummy items for each date between our date range
func setUpItems (startDate: Date, endDate: Date) -> [Item] {
    var date = startDate
    var inputArray: [Item] = []

    let dateCount = cal.dateComponents([.day], from: startDate, to: endDate).day
    let valuePerDay: Double = 1000 / Double(dateCount!)
    let lowerLim = valuePerDay - (valuePerDay / 2)
    let upperLim = valuePerDay + (valuePerDay / 2)

    while date < endDate {
        let input = Double.random(in: lowerLim...upperLim).rounded()
        inputArray.append(Item(
            date: date,
            amount: input
        ))
        date = cal.date(byAdding: .day, value: 1, to: date)!
    }

    return inputArray
}

let itemArray = setUpItems(startDate: startDate, endDate: endDate)


let grouppedByYear = Dictionary(grouping: itemArray, by: { $0.date.year })

let grouppedByYearThenWeek = grouppedByYear
    .mapValues{(yearArray: [Item]) -> Dictionary<Int, Double> in
        return Dictionary(grouping: yearArray, by: { $0.date.week })
            .mapValues{ (value: [Item]) in
                return value.map{ $0.amount }.reduce(0, +)
        }
    }

print("Grouped by week")
print(grouppedByYearThenWeek)

Отсюда вы можете ожидать, что результат будет выглядеть примерно так

Grouped by week
[2018: [49: 127.0, 52: 125.0, 50: 119.0, 51: 113.0, 1: 39.0],
  2019: [3: 124.0, 4: 122.0, 5: 19.0, 1: 87.0, 2: 121.0]]

Я надеюсь, что в итоге я получу словарь, в котором неделя не делится на неделю в зависимости от года

[2018: [49: 127.0, 52: 125.0, 50: 119.0, 51: 113.0],
  2019: [3: 124.0, 4: 122.0, 5: 19.0, 1: 126.0, 2: 121.0]]

// or potentially

[["49 2018": 127.0, "52 2018": 125.0...],
  ["3 2019": 124.0, "4 2019": 122.0...]]

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 31 января 2019

К сожалению, первая неделя года часто присутствует в одном из лет и в следующем.

Да.Но если вы извлекаете неделю года, нет смысла извлекать ее с помощью .year.Вы хотите использовать .yearForWeekOfYear в сочетании с .weakOfYear:

var weekAndYear: DateComponents {
    return cal.dateComponents([.weekOfYear, .yearForWeekOfYear], from: self)
}

var yearForWeekOfYear: Int {
    return cal.component(.yearForWeekOfYear, from: self)
}

И вам может быть полезно иметь вычисляемое свойство начала недели:

var startOfWeek: Date {
    let components = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
    return cal.date(from: components)!
}

Этосводится к тому, как вы хотите, чтобы вы относились к 31 декабря 2018 года. Хотите ли вы, чтобы оно появилось на первой неделе 2019 года (как это делают стандартные weekOfYear и yearForWeekOfYear), или вы хотите отнести его к «53-я неделя 2018 года ».Короче говоря, хотите ли вы рассматривать неделю, начинающуюся 30 декабря 2018 года, как одну неделю (которой достигнет вышеуказанное), или же вы хотите разделить ее, рассматривая начало недели как неделю 53 из 2018 и последнюю частьнедели как 1 недели 2019 года?

...