swift - 如何在 Swift 中实现 CountedSet (NSCountedSet)?
问题描述
创建一个受限于 Hashable 元素的通用 CountedSet 结构。计数集是唯一元素的无序集合,可能在集合中出现多次。使用私有字典作为集合成员及其计数的后备存储。
struct CountedSet<Element> {
private(set) var elements: [Element]
mutating func insert(_ element: Element) {
elements.append(element)
}
mutating func remove() -> Element? {
guard elements.isEmpty == false else { return nil}
return elements.removeFirst()
}
subscript(_ member: Element) -> Int {
return 0
}
}
我不明白这里的真正目的是什么。至少对我来说,这些说明非常令人困惑。
解决方案
1)使您的通用结构元素符合Hashable
,这是必要的,因为字典键必须符合Hashable
。
struct CountedSet<Element: Hashable>
2)您使用的后备存储是有序数组,而不是字典,您需要使用空数组对其进行初始化。
private(set) var elements: [Element: Int] = [:]
3)您的下标方法需要返回计数集成员的计数,如果它为零,则返回零。
return elements[member] ?? 0
4) 您的 Insert 和 Remove 方法需要先检查支持字典中成员的计数,然后再从中添加或删除元素。
所以你的 CountedSet 应该是这样的:
struct CountedSet<Element: Hashable> {
private(set) var elements: [Element: Int] = [:]
mutating func insert(_ member: Element) {
elements[member, default: 0] += 1
}
mutating func remove(_ member: Element) -> Element? {
guard var count = elements[member], count > 0 else { return nil }
count -= 1
elements[member] = count == 0 ? nil : count
return member
}
subscript(_ member: Element) -> Int {
elements[member] ?? 0
}
}
var countedSet = CountedSet<Int>()
countedSet.insert(3)
countedSet.insert(3)
countedSet.insert(4)
countedSet.elements // [4: 1, 3: 2]
countedSet.remove(4)
countedSet.elements // [3: 2]
countedSet.remove(4) // nil
对此进行扩展,您还可以使您的CountedSet
符合以ExpressibleByArrayLiteral
允许您CountedSet
使用数组初始化并CustomStringConvertible
允许您打印其元素:
extension CountedSet: ExpressibleByArrayLiteral, CustomStringConvertible {
typealias ArrayLiteralElement = Element
init<S: Sequence>(_ sequence: S) where S.Element == Element {
self.elements = sequence.reduce(into: [:]) { $0[$1, default: 0] += 1 }
}
init(arrayLiteral elements: Element...) { self.init(elements) }
var description: String { .init(describing: elements) }
}
var countedSet: CountedSet = [1,2,2,3,3,3,4,4,5,5,5]
print(countedSet) // "[5: 3, 2: 2, 3: 3, 4: 2, 1: 1]\n"
推荐阅读
- c# - 在 ASP.NET Core 中使用 UseApplicationInsights/AddApplicationInsights 进行简单的注入器使用
- sql - 关于如何连接表的 SQL 分配
- javascript - jQuery触发事件并发送退格键输入,但输入文本根本无法删除
- sql-server - 不正确的语法错误sql
- python-2.7 - Python编译后“执行失败”
- python - python中基于优先级序列的序列匹配器
- html - 在旋转的 Div 周围环绕文本
- java - 如何使用加速度计按下android中的按钮?
- wordpress - WordPress(找到搜索结果)
- amazon-web-services - Terraform 破坏抛出错误