Set(Collection) - 插入多个元素

时间:2018-02-15 18:38:48

标签: ios swift set tuples swift-extensions

Set是一组无序的独特元素。几乎与数组相似。

我想在Set String中添加/插入多个元素。但是只提供了一种方法,只能插入一个元素(接受单个Set元素作为参数参数),我收集了字符串(id)。

insert(_:)

@discardableResult mutating func insert(_ newMember: Set.Element) -> (inserted: Bool, memberAfterInsert: Set.Element)

我该怎么做?

我尝试了什么: 我尝试创建一个非常类似于insert(_:)方法的扩展,但它可以接受多个Set元素。它与使用迭代而不是集合相同,但不需要在任何地方手动处理它。

extension Set {

    @discardableResult mutating func insert(_ newMembers: [Set.Element]) -> (inserted: Bool, memberAfterInsert: Set.Element) {

        newMembers.forEach { (member) in
            self.insert(member)
        }
    }
}

如果我按预期返回一个元组但不知道如何以及在哪里(哪一行)以及返回值的内容,它应该可以工作。

这是错误消息。

  

在预期返回的函数中缺少返回'(inserted:Bool,memberAfterInsert:Set.Element)'

enter image description here

可以解决这个问题。是否有更好的解决方案/方法来处理此操作?

4 个答案:

答案 0 :(得分:16)

在问题的评论中已经指出,但我想清楚地说明有一种方法可以达到同样的目的:

mutating func formUnion<S>(_ other: S) where Element == S.Element, S : Sequence

用法:

var attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Diana", "Marcia", "Nathaniel"]
attendees.formUnion(visitors)
print(attendees)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"

来源:Apple Developer

还有一个不可变的变量,它返回一个包含union的新实例:

func union<S>(_ other: S) -> Set<Set.Element> where Element == S.Element, S : Sequence

用法:

let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
let attendeesAndVisitors = attendees.union(visitors)
print(attendeesAndVisitors)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"

来源:Apple Developer

答案 1 :(得分:6)

您的insert声明声明该方法返回了一个元组:(inserted: Bool, memberAfterInsert: Set.Element),但您的方法不会返回任何内容。

只需使用:

@discardableResult mutating func insert(_ newMembers: [Set.Element]) {

    newMembers.forEach { (member) in
        self.insert(member)
    }
}

<强>更新

最接近得到的是我相信:

extension Set {

    @discardableResult mutating func insert(_ newMembers: [Set.Element]) -> [(inserted: Bool, memberAfterInsert: Set.Element)] {
        var returnArray: [(inserted: Bool, memberAfterInsert: Set.Element)] = []
        newMembers.forEach { (member) in
            returnArray.append(self.insert(member))
        }
        return returnArray
    }
}

推理:

插页的docs说:

  

返回值

     

(true, newMember)如果集合中未包含newMember。如果集合中已包含等于newMember的元素,则该方法返回(false, oldMember),其中oldMember是等于newMember的元素。在某些情况下,oldMember可能会通过身份比较或其他方式与newMember区分开来。

例如,对于设置{1, 2, 3},如果您尝试插入2,则元组将返回(false, 2),因为2已经存在。元组的第二项是来自集合的对象而不是你提供的对象 - 这里有Ints它是无法区分的,因为只有2的数字等于2,但取决于Equatable实现你可以有两个不同的对象,将被评估为相同。在这种情况下,第二个论点可能对我们很重要。

无论如何,我想说的是,单个元组因此对应于您尝试插入的单个 newMember。如果您尝试插入多个新成员,则无法仅通过使用单个元组来描述该插入 - 其中一些新成员可能已经存在,因此第一个参数将是false,其他一些成员可能成功插入,因此对于他们来说,元组的第一个参数是true

因此,我认为正确的方法是返回一组元组[(inserted: Bool, memberAfterInsert: Set.Element)]

答案 2 :(得分:1)

基本设置操作

enter image description here

union不可变函数,将返回一个新集合,其中包含该集合和给定集合的元素。

func union(_ other: Self) -> Self 

formUnion({{1}之前为Swift版本3)可变函数,将给定集合的元素添加到集合中。

unionInPlace

答案 3 :(得分:1)

我认为您正在寻找的是这个

extension Set {
    
    mutating func insert(_ elements: Element...) {
        insert(elements)
    }
    
    mutating func insert(_ elements: [Element]) {
        for element in elements {
            insert(element)
        }
    }
}

您问题中的示例打破了几个良好的软件编程原则,例如单一职责规则。似乎您的函数正在尝试修改当前集合并返回新集合。那真是令人困惑。您为什么要这么做?

如果您尝试从多个集合中创建一个新集合,则可以执行以下操作:

extension Set { 

    /// Initializes a set from multiple sets. 
    /// - Parameter sets: An array of sets. 
    init(_ sets: Self...) {
        self = []
        for set in sets {
            for element in set {
                insert(element)
            }
        }
    }
}