Swift:用于更新字典值的自定义运算符
是否有一种优雅的方法来生成更新字典值的自定义运算符 更具体地说,我需要一个前缀运算符,它递增与给定键对应的整数值:Swift:用于更新字典值的自定义运算符,swift,custom-operator,Swift,Custom Operator,是否有一种优雅的方法来生成更新字典值的自定义运算符 更具体地说,我需要一个前缀运算符,它递增与给定键对应的整数值: prefix operator +> {} prefix func +> //Signature { ... } var d = ["first" : 10 , "second" : 33] +>d["second"] // should update d to ["first" : 10 , "second" : 34] 这是可行的使用功能的方式
prefix operator +> {}
prefix func +> //Signature
{
...
}
var d = ["first" : 10 , "second" : 33]
+>d["second"] // should update d to ["first" : 10 , "second" : 34]
这是可行的使用功能的方式。例如,要计算阵列中元素的频率,请执行以下操作:
func update<K,V>(var dictionary: [K:V], key: K, value: V) -> [K:V] {
dictionary[key] = value
return dictionary
}
func increment<T>(dictionary: [T:Int], key: T) -> [T:Int] {
return update(dictionary, key: key, value: dictionary[key].map{$0 + 1} ?? 1)
}
func histogram<T>( s: [T]) -> [T:Int] {
return s.reduce([T:Int](), combine: increment)
}
let foo = histogram([1,4,3,1,4,1,1,2,3]) // [2: 1, 3: 2, 1: 4, 4: 2]
func更新(变量字典:[K:V],键:K,值:V)->[K:V]{
字典[键]=值
返回字典
}
函数增量(字典:[T:Int],键:T)->[T:Int]{
返回更新(dictionary,key:key,value:dictionary[key].map{$0+1}??1)
}
func直方图(s:[T])->[T:Int]{
返回s.reduce([T:Int](),combine:increment)
}
设foo=直方图([1,4,3,1,4,1,1,2,3])/[2:1,3:2,1:4,4:2]
但我正试图用一个自定义操作符做同样的事情
var d = ["first" : 10 , "second" : 33]
d["second"]?++
操作员可以这样实现:
prefix operator +> {}
prefix func +> <I : ForwardIndexType>(inout i: I?) {
i?._successorInPlace()
}
var dict = ["a":1, "b":2]
+>dict["b"]
dict // ["b": 3, "a": 1]
:
或者,使用未记录的函数:
extension SequenceType where Generator.Element : Hashable {
func frequencies() -> [Generator.Element:Int] {
var result: [Generator.Element:Int] = [:]
for el in self {result[el]?._successorInPlace() ?? {result[el] = 1}()}
return result
}
}
prefix operator +> {}
prefix func +>(inout n: Int) {
n++
}
这可能比您想要的要难看一点,但您可以在通用重载运算符中使用不安全的可变指针来完成:
prefix operator +> {}
prefix func +><T>( value:UnsafeMutablePointer<T?> )
{
print( value.memory )
if let intValue = value.memory as? Int {
value.memory = (intValue + 1) as? T
}
}
var d = ["first" : 10 , "second" : 33]
print( d["second"] ) // Optional(33)
+>(&d["second"])
print( d["second"] ) // Optional(34)
前缀运算符+>{}
前缀func+>(值:UnsafeMutablePointer)
{
打印(value.memory)
如果让intValue=value.memory为?Int{
value.memory=(intValue+1)为?T
}
}
变量d=[“第一”:10,“第二”:33]
打印(d[“秒])//可选(33)
+>(&d[“第二”])
打印(d[“秒])//可选(34)
首先,寻找一种使用函数(而不是自定义运算符)的方法。您需要一个函数,该函数引用一个项(来自字典)并更新其值。。。这需要一个inout
参数类型
func increment(inout n: Int) {
n++
}
var d = ["first" : 10 , "second" : 33]
increment(&d["first"]!)
print(d) // -> "[first: 11, second: 33]"
您不必关心字典中的值-inout
接受任何类型的引用并直接更新它。(这甚至适用于计算属性。您可以传递一个inout
,它将在读取和写入值时正确地通过setter和getter。)并且因为您不必关心字典,您实际上不需要泛型-如果您想要一个在Int
的字典上工作的函数,只需创建一个在Int
s上工作的函数,然后让inout
完成其余的工作
现在,自定义运算符只是函数,因此请为函数创建一个运算符:
extension SequenceType where Generator.Element : Hashable {
func frequencies() -> [Generator.Element:Int] {
var result: [Generator.Element:Int] = [:]
for el in self {result[el]?._successorInPlace() ?? {result[el] = 1}()}
return result
}
}
prefix operator +> {}
prefix func +>(inout n: Int) {
n++
}
但是,您不能完全使用您要求的语法来调用它:字典查找总是导致可选类型,因此您必须展开
+>d["second"] // error
+>d["second"]! // but this works — operators automatically make params inout as needed
print(d) // -> "[first: 11, second: 34]"
你的
++>
与++
做的事情几乎完全一样,不是吗?我是说,++d[“秒”]代码>效果很好。不过,对我来说,强制展开会扼杀它。相反,我会这样做:prefix func++>(inout n:Int?{n?++}
@oisdk是的,但OP显然询问了一个自定义运算符定义,一般来说,++>
的主体不一定要执行增量。正是这条推特让我来到这里。。也许只是xcode beta 4有一个bug,不知道如何处理++
操作。我忘记了inout
,我也喜欢rickster的答案。