集合(Collection)——插入多个元素

Set (Collection) - Insert multiple elements

Set 是唯一元素的无序集合。和数组差不多。

我想 add/insert 多个元素 Set of 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)
        }
    }
}

如果我按预期 return 一个元组但不知道如何以及在哪里(哪一行)以及 return 一个值是什么,它应该可以工作。

这是错误信息。

Missing return in a function expected to return '(inserted: Bool, memberAfterInsert: Set.Element)'

有什么办法可以解决这个问题。有没有更好的solution/approach来处理这个操作?

您的 insert 声明指出该方法正在 return 元组:(inserted: Bool, memberAfterInsert: Set.Element),但您的方法没有 return 任何东西。

只需使用:

@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说:

Return Value

(true, newMember) if newMember was not contained in the set. If an element equal to newMember was already contained in the set, the method returns (false, oldMember), where oldMember is the element that was equal to newMember. In some cases, oldMember may be distinguishable from newMember by identity comparison or some other means.

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

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

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

问题下的评论中指出了这一点,但我想明确说明有一种方法可以达到同样的目的:

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


还有一个不可变变体 returns 包含联合的新实例:

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

a.union(b) - a ∪ b - 结果集包含来自 ab[= 的所有元素19=]

union - 不可变 函数
unionInPlace(最多 Swift 3)=> formUnion - 可变 函数

[Mutable vs Immutable]

阅读更多here

我想你要找的是这个:

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

您问题中的示例打破了一些好的软件编程原则,例如单一职责规则。看起来您的函数正在尝试同时修改当前集和 return 新集。这真是令人困惑。为什么你会想要那样做?

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

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