swift - 如何调整字典的值以快速阅读?
问题描述
已编辑的问题:如何快速调整字典的值以供阅读?
我想在不改变原点的情况下调整字典的值以供阅读。我实现了以下类来做到这一点。
class DictionaryView<Key, Value> where Key: Hashable {
let origin: Dictionary<Key, Value>
let map: (Value) -> Value
init(_ origin: Dictionary<Key, Value>,
map: @escaping (Value) -> Value) {
self.origin = origin
self.map = map
}
subscript(_ key: Key) -> Value?{
let value = origin[key]
return value == nil ? value : map(value!)
}
}
但没有像我预期的那样工作。以下代码
var origin = ["A":2, "B":3]
var adapted = DictionaryView(origin, map: { $0 * 2 })
origin["C"] = 6
print(origin)
print(adapted["A"])
print(adapted["B"])
print(adapted["C"])
给我输出:
["B": 3, "C": 6, "A": 2]
可选(4)
可选(6)
无
我需要进行调整,以打印 Optional(12) insted of nil。怎么做?
原始问题:如何快速调整字典的值?
我有一本字典origin
var origin = ["A":2, "B":3]
并希望创建一个基于origin
但包含双值的新字典。我天真的解决方案是通过mapValues
var adapted = origin.mapValues { $0 * 2 }
但是这个解决方案会根据origin
' 状态的时刻创建一个新的转换字典。例如下面的代码
origin["C"] = 6
print(origin)
print(adapted)
输出
[“A”:1,“B”:2,“C”:6]
[“A”:2,“B”:4]
但我想要真正的适应。我需要一个解决方案,它将为上面的代码输出如下结果。
[“A”:1,“B”:2,“C”:6]
[“A”:2,“B”:4,“C”:12]
我是 swift 新手,对标准库没有深入的了解。在开始自行车设计之前,我要问:快速解决这个问题的常见方法是什么?
备注 1
我在真实情况下发现了问题,但创建了一个简化示例来提取当前问题的问题本质(避免细节的干扰)。但正如我所看到的,有必要澄清这个问题。
我需要实现 observable 模式并在 Observable.swift 文件中开发了它的 4 个部分。
订阅:
struct Subscription {
private let handler: () -> ()
init(cancel handler: @escaping () -> ()) {
self.handler = handler
}
func cancel() {
handler()
}
}
观察员:
struct Observer<Event> {
private let handler: (Event) -> ()
init(send handler: @escaping (Event) -> ()) {
self.handler = handler
}
func send(_ event: Event) {
handler(event)
}
}
可观察的:
class Observable<Event> {
fileprivate var observers: [UUID : Observer<Event>] = [:]
func subscribe(_ observer: Observer<Event>) -> Subscription {
let id = UUID()
observers[id] = observer
return Subscription(cancel: { self.observers[id] = nil })
}
}
主题:
class Subject<Event> : Observable<Event> {
private(set) lazy var observer = Observer<Event>(
send: { event in
for o in self.observers.values {
o.send(event)
}})
}
作为一个常见的例子,我在客户端类外部提供了一个 Subject 作为 Observable 的实例,并在内部用作 Observer 以进行良好的封装。使用示例:
class Acc {
private let numberAdded: Observer<Int>
let numberDidAdd: Observable<Int>
init() {
let subject = Subject<Int>()
numberAdded = subject.observer
numberDidAdd = subject
}
func add(_ number: Int) {
numberAdded.send(number)
}
}
let acc = Acc()
acc.numberDidAdd.subscribe(Observer<Int>(send: { print($0) }))
acc.add(4)
acc.add(5)
当我需要一个简单的事件时,这个解决方案对我很有用。当我需要实现更复杂的事件订阅接口时,问题就开始了。我需要提供一个事件字典(外部观察者,内部观察者)。以下代码是真实上下文的一部分。描述这种上下文并不容易,但我认为可以从代码中捕捉到它。
class RealClass {
let buttonEvents = ButtonEvents()
override func viewDidLoad() {
super.viewDidLoad()
for (event, observer) in buttonEvents.observers {
someInternalSubscriptionFunc(event, observer)
}
buttonEvents.newEventTypeDidAdd.subscribe(
Observer(send: { event in
self.someInternalSubscriptionFunc(
event, self.buttonEvents.observers[event]!)
})
}
public class ButtonEvents {
private let newEventTypeAdding = Subject<UIControl.Event>()
private(set) lazy var newEventTypeDidAdd
: Observable<UIControl.Event>
= newEventsTypeAdding
private var subjects: [UIControl.Event : Subject<Point>] = [:]
fileprivate private(set) lazy var observers
: [UIControl.Event : Observer<Point>]
= subjects.mapValues({ subject in subject.observer })
public subscript(event: UIControl.Event) -> Observable<Point> {
if subjects[event] == nil {
subjects[event] = Subject<Point>()
newEventTypeAdding.send(event)
}
return subjects[event]!
}
}
}
正如我们所见ButtonEvents.observers
,这是问题的根源。
我可以重新实现observers
为计算属性,但在访问字典项时我会失去 O(1) 的性能。
解决方案
发生这种情况是因为
字典是值类型
你应该在这里做的是使用Computed Property
var adapted: [String: Int] {
return origin.mapValues { $0 * 2 }
}
现在在任何地方调用它,结果将符合预期
推荐阅读
- reactjs - useSWR 变异函数未按预期工作
- angular - .NET 6 中的 Angular 项目
- node.js - 如何使用 JSdoc 引用另一个文件中的普通对象?
- sql - 为什么 SQL 浮点转换为字符串不能与 LIKE 一起使用,但 SQL 浮点转换为十进制转换为字符串可以?
- python - Python:一组可以同时或单独绘制的门
- reactjs - Redux 状态更新
- email - Outlook.com 中的暗模式
- safari - 通过 AirPlay 在 Safari 中启用 FairPlay 流式传输
- mysql - 当 repo IP 不断变化时,如何让 mysql yum repo 的防火墙规则持续存在?
- c# - 是否可以使用 .NET 6 中的 .NET 4.8 库?