Swift数组减少:不能在不可变值上使用变异成员

时间:2016-06-28 05:36:48

标签: swift functional-programming immutability

我有以下代码尝试合并数组的冗余元素:

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。什么错了,我该如何解决?

3 个答案:

答案 0 :(得分:2)

在Swift中,集合是值类型。使用let声明的值类型变量(隐式地是函数参数)无法修改。此外,您的闭包不返回任何内容,因此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)

答案 1 :(得分:2)

OP代码的问题在于reduce中的累加器是不可变的,所以它不允许你使用变异函数insert()。

一个整洁的解决方案是在如下的Set的扩展中定义一个名为insertion()的insert()的非变异等价物。

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)
}

答案 2 :(得分:0)

返回的'set'值是一个常量。这很重要,因为它是累加器,它表示迄今累积的值。它不应该在关闭时改变。

以下是我正在进行的一个项目的示例,我希望在许多戏剧表演中找到所有独特的表演者。注意我如何使用union,它不会修改常量值'performers',而是使用它来产生一个新值。

RouteBase