Swift 数组缩减:不能对不可变值使用可变成员
Swift array reduction: cannot use mutating member on immutable value
我有以下代码试图合并数组的冗余元素:
var items : [String] = ["hello", "world", "!", "hello"]
var mutableSet = Set<String>()
items.reduce(mutableSet, combine: { (set: Set<String>, element: String) in
return set.insert(element)
})
set.insert(element)
给我错误 Cannot use mutating member on immutable value: 'set' is a 'let' constant
。出了什么问题,我该如何解决?
在Swift中,集合是值类型。不能修改用 let
声明的值类型变量(函数参数隐含)。此外,您的闭包 returns 什么都没有,因此 reduce
可能不会成功。
我认为 reduce
不是完成这项任务的最佳工具。考虑这个 for
循环:
var set = Set<String>()
for element in items { set.insert(element) }
另一个更简单的选择是使用 unionInPlace
方法:
var set = Set<String>()
set.unionInPlace(items)
也许更好的是,直接从集合中创建集合:
var set = Set<String>(items)
返回的'set'值是一个常量。这一点很重要,因为它是累加器,它代表到目前为止已经累积的值。它不应该在你的关闭中改变。
这是我目前正在进行的一个项目的示例,我想在其中找到所有独特的表演者,跨越许多戏剧演出。请注意我是如何使用 union 的,它不会修改常量值 'performers',而是使用它来产生一个新值。
let uniquePerformers = performances.reduce(Set<Performer>(), { (performers: Set<Performer>, performance) -> Set<Performer> in
return performers.union(Set(performance.performers))
})
OP 代码的问题在于 reduce 中的累加器是不可变的,因此它不允许您使用变异函数 insert()。
一个简洁的解决方案是在 Set 的扩展中定义一个与 insert() 等效的非变异等效项,称为 inserting(),如下所示。
extension Set {
//returns a new set with the element inserted
func inserting(_ element: Element) -> Set<Element> {
var set = self
set.insert(element)
return set
}
}
现在我们可以这样写reduce
var items : [String] = ["hello", "world", "!", "hello"]
let set = items.reduce(Set<String>()){ accumulator, element in
accumulator.inserting(element)
}
我有以下代码试图合并数组的冗余元素:
var items : [String] = ["hello", "world", "!", "hello"]
var mutableSet = Set<String>()
items.reduce(mutableSet, combine: { (set: Set<String>, element: String) in
return set.insert(element)
})
set.insert(element)
给我错误 Cannot use mutating member on immutable value: 'set' is a 'let' constant
。出了什么问题,我该如何解决?
在Swift中,集合是值类型。不能修改用 let
声明的值类型变量(函数参数隐含)。此外,您的闭包 returns 什么都没有,因此 reduce
可能不会成功。
我认为 reduce
不是完成这项任务的最佳工具。考虑这个 for
循环:
var set = Set<String>()
for element in items { set.insert(element) }
另一个更简单的选择是使用 unionInPlace
方法:
var set = Set<String>()
set.unionInPlace(items)
也许更好的是,直接从集合中创建集合:
var set = Set<String>(items)
返回的'set'值是一个常量。这一点很重要,因为它是累加器,它代表到目前为止已经累积的值。它不应该在你的关闭中改变。
这是我目前正在进行的一个项目的示例,我想在其中找到所有独特的表演者,跨越许多戏剧演出。请注意我是如何使用 union 的,它不会修改常量值 'performers',而是使用它来产生一个新值。
let uniquePerformers = performances.reduce(Set<Performer>(), { (performers: Set<Performer>, performance) -> Set<Performer> in
return performers.union(Set(performance.performers))
})
OP 代码的问题在于 reduce 中的累加器是不可变的,因此它不允许您使用变异函数 insert()。
一个简洁的解决方案是在 Set 的扩展中定义一个与 insert() 等效的非变异等效项,称为 inserting(),如下所示。
extension Set {
//returns a new set with the element inserted
func inserting(_ element: Element) -> Set<Element> {
var set = self
set.insert(element)
return set
}
}
现在我们可以这样写reduce
var items : [String] = ["hello", "world", "!", "hello"]
let set = items.reduce(Set<String>()){ accumulator, element in
accumulator.inserting(element)
}