Мне нужна помощь, чтобы создать новый массив в Swift 2.0.

У меня есть два массива, один содержит даты, а другой - платежи на эту дату.

let year = [February 2016, March 2016, June 2017, October 2017, January 2018, April 2019] // Data at which a payment is initiated
let payment = ["1000","2000,"3000","1000","2000,"3000"] // payment amount at date in array year

На основе этого я хотел бы создать два новых массива в коде Swift. Окончательный результат должен выглядеть так:

let yearSum [2016, 2017, 2018,2019]  // only full year 
let paymentSum ["3000","4000","2000","3000"] // sum of all payment in the year

Массив yearSum должен содержать только полный номер года, а paymentSum - сумму всех платежей за год.

Есть ли у кого-нибудь совет, как я могу это закодировать?

Большое спасибо

2
Marcus 28 Фев 2016 в 22:26

2 ответа

Лучший ответ

Вход

Прежде всего, дадим хорошие имена входным константам.

let monthStrings = ["February 2016", "March 2016", "June 2017", "October 2017", "January 2018", "April 2019"]
let paymentStrings = ["1000", "2000", "3000", "1000", "2000", "3000"]

Что может пойти не так

Мы работаем со строками в качестве входных данных, поэтому многие вещи могут пойти не так во время синтаксического анализа Date или Int. Для ясности определим следующее перечисление

enum Error: ErrorType {
    case InputParamsHaveDifferentSizes(Int, Int)
    case FirstParamHasInvalidDate
    case SecondParamHasInvalidInt
}

Функция

func groupData(monthStrings: [String], paymentsStrings:[String]) throws -> [Int:Int] {
    // make sure both arrays have the same size
    guard monthStrings.count == paymentStrings.count
        else { throw Error.InputParamsHaveDifferentSizes(monthStrings.count, paymentStrings.count) }

    let formatter = NSDateFormatter()
    formatter.dateFormat = "MMM yyyy"

    // creates dates: an array of NSDate representing monthStrings
    // if dates has a different size of monthsString then throws and error
    guard
        case let dates = (monthStrings.flatMap { formatter.dateFromString($0) })
        where dates.count == monthStrings.count
        else { throw Error.FirstParamHasInvalidDate }

    // creates payments: an array of Int representing paymentsStrings
    // if payments has a different size of paymentsStrings then throws and error
    guard
        case let payments = (paymentStrings.flatMap { Int($0) })
        where payments.count == paymentStrings.count
        else { throw Error.SecondParamHasInvalidInt }

    // put togheter dates and payments and group the results by year
    return zip(dates, payments).reduce([Int:Int]()) { (var result, elm) -> [Int:Int] in
        let year = NSCalendar.currentCalendar().components([NSCalendarUnit.Year], fromDate: elm.0).year
        result[year] = elm.1 + (result[year] ?? 0)
        return result
    }
}

Применение

let res = try groupData(monthStrings, paymentsStrings: paymentStrings)
print(res) // [2018: 2000, 2017: 4000, 2016: 3000, 2019: 3000]

Обновить

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

let sortedKeys = res.keys.sort()

func value(index:Int) -> String? {
    let key = sortedKeys[index]
    let value = res[key]
    return value
}
3
Luca Angeletti 1 Мар 2016 в 16:34

Что ж, из-за отсутствия ответа я просто предполагаю, что years - это массив строк:

// Data
let years = ["February 2016", "March 2016", "June 2017", "October 2017", "January 2018", "April 2019"]
let payed = ["1000", "2000", "3000", "1000", "2000", "3000"]

// Preparation    
var result: [String: Double] = [:]
let digits = NSCharacterSet.decimalDigitCharacterSet().invertedSet

// Results
let yearOnly = years.flatMap { $0.componentsSeparatedByCharactersInSet(digits).filter { !$0.isEmpty } }
zip(yearOnly, payed).forEach { result[$0.0] = (result[$0.0] ?? 0) + (Double($0.1) ?? 0) }

Обратите внимание, что yearOnly создается путем фильтрации всех нецифровых чисел, поэтому, если у вас будут дни внутри years, это не сработает, и вам придется использовать другой метод для фильтрации лет.

// Output
["2018": 2000.0, "2019": 3000.0, "2016": 3000.0, "2017": 4000.0]
0
Eendje 28 Фев 2016 в 20:10