我如何“追加”到Swift中的不可变字典? [英] How do I "append" to an immutable dictionary in Swift?

查看:128
本文介绍了我如何“追加”到Swift中的不可变字典?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scala中, +(k - > ; v)在 immutable.Map 上的 运算符返回一个新的 immutable.Map 与原始内容一起加上新的键/值对。同样,在C#中, ImmutableDictionary.add(k,v) 返回一个新的,更新的 ImmutableDictionary

然而,在Swift中, Dictionary 似乎只有变异 updateValue(v,forKey:k)函数和变异 [k:v] 运算符。



我想也许我可以用 flatten()来玩一些技巧,但是没有运气:

  let updated = [original,[newKey:newValue]]。flatten()

得到我

 无法转换类型'() - >>的值; FlattenCollection< [[String:AnyObject]]>'
到指定的类型'[String:AnyObject]'

如何从现有的内容创建新的,已修改的不可变 Dictionary






更新:根据此答案'请注意,Swift词典是值类型,并且这个答案的可变版本,我提出了下面的扩展操作符,但我对此并不感到兴奋 - 似乎必须有一个更清洁的开箱即用的替代品。

  func + (左:[K:V],右:[K:V]) - > [K:V] {
var union = left
for(k,v)in right {
union [k] = v
}
return union





$ b但是也许事实(如果我理解正确的话)Swift字典的不变性是一个编译器检查 let 而不是不同的实现类的问题意味着这是最好的可以完成的?





更新2: Jules的回答,修改不经过特别优化的不可变字典以共享副本之间的状态(因为Swift字典不是)会出现性能问题。对于我当前的用例( AttributedString 属性字典,它们通常很小),它仍然可以简化某些值得做的事情,但直到并且除非Swift实现共享状态不变的字典在一般情况下它可能不是一个好主意 - 这是一个不把它作为内置功能的好理由。

解决方案

不幸的是,这是一个很好的问题,因为答案是你不能。还没有,无论如何 - 其他人同意这应该被添加,因为有一个 Swift Evolution对此的建议(以及其他缺少的 Dictionary 功能)。目前它正在等待审核,所以你可能会看到 merged()方法,它基本上是你的 + 操作符版本的Swift!



与此同时,您可以使用您的解决方案追加整个词典,或一次添加一个值:

 扩展词典{
func appending(_ key:Key,_ value:Value) - > [Key:Value] {
var result = self
result [key] = value
return result
}
}


In Scala, the + (k -> v) operator on immutable.Map returns a new immutable.Map with the contents of the original, plus the new key/value pair. Similarly, in C#, ImmutableDictionary.add(k, v) returns a new, updated ImmutableDictionary.

In Swift, however, Dictionary appears only to have the mutating updateValue(v, forKey: k) function and the mutating [k:v] operator.

I thought maybe I could play some trick with flatten(), but no luck:

let updated = [original, [newKey: newValue]].flatten()

gets me

Cannot convert value of type '() -> FlattenCollection<[[String : AnyObject]]>' 
to specified type '[String : AnyObject]'

How do I create a new, modified immutable Dictionary from the contents of an existing one?


Update: Based on this answer's note that Swift dictionaries are value types, and this answer's mutable version, I came up with the following extension operator, but I'm not excited about it -- it seems like there must be a cleaner out-of-the-box alternative.

func + <K, V>(left: [K:V], right: [K:V]) -> [K:V] {
    var union = left
    for (k, v) in right {
        union[k] = v
    }
    return union
} 

But maybe the fact (if I understand correctly) that the immutability of Swift dictionaries is a compiler check on let rather than a matter of different implementation classes means this is the best that can be done?


Update #2: As noted in Jules's answer, modifying immutable dictionaries that aren't specifically optimized to share state between copies (as Swift dictionaries aren't) presents performance problems. For my current use case (AttributedString attribute dictionaries, which tend to be fairly small) it may still simplify certain things enough to be worth doing, but until and unless Swift implements a shared-state immutable dictionary it's probably not a good idea in the general case -- which is a good reason not to have it as a built-in feature.

解决方案

Unfortunately, this is a good question because the answer is "you can't". Not yet, anyway--others agree this should be added, because there's a Swift Evolution proposal for this (and some other missing Dictionary features). It's currently "awaiting review", so you may see a merged() method that's basically your + operator in a future version of Swift!

In the meantime, you can use your solution to append entire dictionaries, or for one value at a time:

extension Dictionary {
    func appending(_ key: Key, _ value: Value) -> [Key: Value] {
        var result = self
        result[key] = value
        return result
    }
}

这篇关于我如何“追加”到Swift中的不可变字典?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆