当 Set 在 Swift 中是可选的时,如何定义 Set 的插入函数?



我的目标是能够将新项目插入到该集合之前具有零值的可选集合中。出于这个原因,我创建了这个扩展,但它不起作用,而且我仍然无法将新项目插入到零集中。

extension Optional where Wrapped == Set<String> {
func myInsert(_ value: String) -> Self {
if let unwrappedSet: Set<String> = self {
var newSet: Set<String> = unwrappedSet
newSet.insert(value)
return newSet
}
else {
let set: Set<String>? = [value]
return set
}
}
}

用例:

func myTest() -> Set<String>? {
var set: Set<String>? = nil
set.myInsert("Hello")
return set
}
if let set: Set<String> = myTest() {
print(set)
}

我拒绝相信我的扩展有问题,我认为问题来自 xcode 本身,看看它下面的函数是相同的函数,但在扩展之外,它确实有效!

func myInsert(set: Set<String>?, value: String) -> Set<String>? {
if let unwrappedSet: Set<String> = set {
var newSet: Set<String> = unwrappedSet
newSet.insert(value)
return newSet
}
else {
let set: Set<String>? = [value]
return set
}
}

用例:

let set: Set<String>? = nil
let newSet = myInsert(set: set, value: "Hello")
let newSet2 = myInsert(set: newSet, value: "World")
print(newSet2)

结果:

可选(设置(["你好", "世界"]))

从测试用例代码:

var set: Set<String>? = nil
set.myInsert("Hello")

您希望变量setnil更改为包含String"Hello"的包装Set<String>。 为了使值自行修改,必须mutatingfunc

myInsert设为mutatingfunc并将新set分配给self。 由于myInsertmutating,因此它不需要返回您的测试忽略的值:

extension Optional where Wrapped == Set<String> {
mutating func myInsert(_ value: String) {
if self == nil {
self = [value]
} else {
self?.insert(value)
}
}
}
<小时 />

测试

func myTest() -> Set<String>? {
var set: Set<String>? = nil
set.myInsert("Hello")
set.myInsert("Goodbye")
return set
}
if let set = myTest() {
print(set)
}
["Hello", "Goodbye"]
<小时 />

使insert更易于使用

(感谢@LeoDabus的建议)

我们可以使用任何类型的Set来使其工作,并通过让它返回一个包含元组的@discardableResult,并带有一个指示值是否已插入的BoolmemberAfterInsert,使其更像Set上的原始insert

extension Optional where Wrapped: SetAlgebra {
@discardableResult
mutating func insert(_ newMember: Wrapped.Element) -> (inserted: Bool, memberAfterInsert: Wrapped.Element) {
if self == nil {
self = .init()
}
return self!.insert(newMember)
}
}

vacawama 和 Leo 的答案是正确的,但你想了解为什么你的代码不起作用。我将尝试解释为什么无法按预期工作。您创建的函数"myInsert"定义了一个 Set 对象,插入参数值并返回新创建的 Set 对象。问题是您实际上并没有将创建的 Set 对象分配给您正在处理的实际 Set 变量(即"self")。

if let unwrappedSet: Set<String> = self {
var newSet: Set<String> = unwrappedSet // assigning nil valued "self" to a variable doesn't assign the original variable. Assigning nil to another variable makes that variable again nil. Both are equal (they are nil) but not same variables.
newSet.insert(value) // inserts value to second Set object not to "self". So still, your actual Set doesn't contains the given value.
return newSet // returns the value inserted Set object, not "self".
}
else {
let set: Set<String>? = [value]
return set
}

如果我们查看 myTest() 函数,您可以看到您的添加操作不适用于实际变量。

var set: Set<String>? = nil
set.myInsert("Hello") // at this point, myInsert function returns a new Set object with inserted given value. But this operation does not effect the original variable above. That means set variable is still nil
return set // returns nil variable.

我希望这有所帮助。

相关内容

最新更新