В настоящее время я создаю приложение для клонирования банковских операций, и одна из вещей, которые я пытаюсь сделать, - это добавить «Разделить транзакцию» (которой затем можно поделиться с несколькими друзьями, оплачивающими определенную сумму каждому).
Первоначально транзакция распределяется поровну между друзьями (если только она не распределяется поровну, в этом случае остаток добавляется к одному незадачливому другу).Затем пользователь может вручную отрегулировать сумму, которую платит каждый, а затем обновить остальные.Если пользователь вручную настроил сумму для друга, этот разделитель друзей не обновляется автоматически, если пользователь затем настраивает сумму другого друга (т. Е. Если пользователь говорит, что friend1 платит 12 фунтов стерлингов, то всегда будет 12 фунтов, покапользователь говорит иначе).
Я некоторое время возился, пытаясь сделать метод максимально лаконичным и «быстрым», но я был бы очень признателен за любые отзывы о моем подходе.
Для целей здесь я только пытаюсь разделить деньги поровну между людьми (но я все же хотел объяснить «разделение по определению пользователя», чтобы текущий код имел смысл).
Я использую https://github.com/Flight-School/Money для представления значения транзакции, все в пределах класса транзакции.Мне нужно немного округлить, чтобы обеспечить разделение и остаток до 2 десятичных знаков.Вот соответствующий код:
Структура для хранения суммы вместе с тем, если пользователь установил ее или нет (должен быть настраиваемым объектом по кодируемым причинам):
struct SplitTransactionAmount: Codable {
let amount: Money<GBP>
let setByUser: Bool
}
Словарь для храненияимена друзей, а также их разделение, и, если оно установлено пользователем, - также массив namesOfPeopleSplittingTransaction для удобного отображения.
var splitTransaction: [String: SplitTransactionAmount]
var namesOfPeopleSplittingTransaction = [String]()
А вот метод разделения транзакции:
private func splitTransaction(amount: Money<GBP>, with friends: [String]) -> [String: SplitTransactionAmount] {
//First we remove any duplicate names.
let uniqueFriends = friends.removingDuplicates()
//Create an empty dictionary to hold the new values before returning.
var newSplitTransaction = [String: SplitTransactionAmount]()
let totalAmountToSplitRounded = amount.rounded.amount
let numberOfSplitters = uniqueFriends.count
let eachTotalRaw = totalAmountToSplitRounded / Decimal(numberOfSplitters)
let eachTotalRounded = Money<GBP>(eachTotalRaw).rounded.amount
let remainder = totalAmountToSplitRounded - (Decimal(numberOfSplitters) * eachTotalRounded)
if remainder == 0 {
//If the amount to split each goes in to the total with no remainder, everyone pays the same.
for friend in uniqueFriends {
newSplitTransaction[friend] = SplitTransactionAmount(amount: Money(eachTotalRounded), setByUser: false)
}
} else {
for friend in uniqueFriends {
if friend == uniqueFriends.first! {
//Unlucky first friend has to pay a few pence more!
newSplitTransaction[friend] = SplitTransactionAmount(amount: Money(eachTotalRounded + remainder), setByUser: false)
} else {
newSplitTransaction[friend] = SplitTransactionAmount(amount: Money(eachTotalRounded), setByUser: false)
}
}
}
return newSplitTransaction
}
Я думаю, что проблема, которую я нахожу, состоит в том, что код имеет для меня смысл, но я не уверен, насколько он понятен внешнему читателю.Любые мысли о моем подходе будут высоко оценены (и извините за длинный вопрос!).И я также хотел бы знать, есть ли в любом случае, чтобы написать это более кратко!
Большое спасибо