我试图了解以下哪种方法更好。
我有Array
的{{1}}
struct
如果我想知道是否已选择任何元素,是否应该每次都遍历项目。
struct A {
var selectionCount: Int
}
var ayes = [A]()
存储一个func selectedCount() -> Int {
return ayes.filter({ $0.selectionCount != 0 }).reduce(0, +)
}
// OR
并在每次我想知道是否进行选择时都进行访问。
var
答案 0 :(得分:2)
区分接口和实现非常重要。首先设计所需的接口,然后可以随时更改内部实现以适应您的(性能与存储)需求。
我认为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
替代实施-相同的界面
此解决方案结合了使用字典的@RakeshaShastri's suggestion和保持计数的想法:
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
}
}
这避免了对预分配数组的需求,但仍可以通过字典和内部计数快速访问。
答案 1 :(得分:1)
我认为有一种甚至更好的方法。
由于您已经在数组中存储了信息-进行选择后,将所选元素的索引存储在另一个数组中。
如果您想知道是否已选择特定元素,则只需检查该元素的索引是否在数组中即可。
如果您想知道所选项目的总数,只需获取数组的数量即可。
基于评论的改进解决方案:
最后,一个更好的解决方案是将所选索引的计数存储在字典中,其中键将是 index ,而 count < / strong>为值。
如果要检查是否选择了特定元素,则可以检查将索引作为键传递给字典时索引是否返回值。
如果要计算唯一选择项的数量,请获取字典中键的数量。
如果要计算选择数量,请获取字典中值的总和。
注意:当所选计数达到0时,您需要从字典中删除键。
答案 2 :(得分:0)
我倾向于反对存储可以从现有数据中得出的信息。但是,这种方法可能对性能至关重要。因此出现了两个问题:
答案 3 :(得分:0)
如果性能是“更好的方法”的含义,那么拥有现成的价值当然比遍历数百个(如果不是数千个)元素并获取其属性然后将它们加起来要快得多。
如果“更好的方法”意味着更好的API设计,则前者的用途更加广泛,因为从您的代码中,任何对象调用select(at:)
或deselect(at:)
都会使selectionCount
变为否定。 。并且您的代码将是有状态的,它将依赖于变量的状态。