Важно отличать интерфейс от реализации . Сначала спроектируйте нужный интерфейс, а затем вы всегда можете изменить внутреннюю реализацию в соответствии с вашими потребностями (производительность или объем памяти).
Я считаю, что массив A
должен быть защищен, и вам следует разрешить доступ только через методы select(at:)
и deselect(at:)
. Это позволяет вам выполнить внутреннюю реализацию в любом случае:
struct Ayes {
private struct A {
var selectionCount = 0
}
private var ayes = [A](repeating: A(), count: 100)
private var totalSelectedElements = 0
mutating func select(at: Int) {
ayes[at].selectionCount += 1
totalSelectedElements += 1
}
mutating func deselect(at: Int) {
guard ayes[at].selectionCount > 0 else { return }
ayes[at].selectionCount -= 1
totalSelectedElements -= 1
}
func selectCount(at: Int) -> Int {
return ayes[at].selectionCount
}
var totalElements: Int {
return totalSelectedElements
}
}
Это действительно зависит от того, как часто вы будете получать доступ к totalElements
, хотите ли вы сохранить его или вычислить. Скрывая детали реализации, вы можете свободно изменять реализацию, не затрагивая остальную часть вашей программы.
Мне нравится идея поддержания подсчета для быстрого доступа, и, защищая доступ к внутренней реализации, вы можете гарантировать точность подсчета.
Пример:
var ayes = Ayes()
print(ayes.totalElements) // 0
ayes.select(at: 3)
ayes.select(at: 3)
ayes.select(at: 4)
print(ayes.totalElements) // 3
print(ayes.selectCount(at: 3)) // 2
ayes.deselect(at: 3)
print(ayes.selectCount(at: 3)) // 1
ayes.deselect(at: 3)
print(ayes.selectCount(at: 3)) // 0
ayes.deselect(at: 3)
print(ayes.selectCount(at: 3)) // 0
print(ayes.totalElements) // 1
Альтернативная реализация - тот же интерфейс
Это решение объединяет @ предложение Ракеша Шастри об использовании словаря с вашей идеей ведения счета:
struct Ayes {
private var ayes = [Int : Int]()
private var totalSelectedElements = 0
mutating func select(at: Int) {
ayes[at, default: 0] += 1
totalSelectedElements += 1
}
mutating func deselect(at: Int) {
guard var count = ayes[at] else { return }
count -= 1
totalSelectedElements -= 1
ayes[at] = count == 0 ? nil : count
}
func selectCount(at: Int) -> Int {
return ayes[at, default: 0]
}
var totalElements: Int {
return totalSelectedElements
}
}
Это позволяет избежать необходимости в предварительно выделенном массиве, но все же обеспечивает быстрый доступ через словарь и внутренний счетчик.