10 ответов:
начиная с Swift 1.2 (Xcode 6.3 beta), Swift имеет собственный тип набора. Из примечаний к выпуску:
новая
Setструктура данных, которая обеспечивает универсальную коллекция уникальных элементов, с полной семантикой значения. Это мосты сNSSet, обеспечивая функциональность аналогичнаArrayиDictionary.вот несколько простых примеров:
// Create set from array literal: var set = Set([1, 2, 3, 2, 1]) // Add single elements: set.insert(4) set.insert(3) // Add multiple elements: set.unionInPlace([ 4, 5, 6 ]) // Swift 3: set.formUnion([ 4, 5, 6 ]) // Remove single element: set.remove(2) // Remove multiple elements: set.subtractInPlace([ 6, 7 ]) // Swift 3: set.subtract([ 6, 7 ]) print(set) // [5, 3, 1, 4] // Test membership: if set.contains(5) { print("yes") }но есть гораздо больше методов доступный.
обновление: наборы теперь также документированы в "Типы Коллекций" глава документации Swift.
Swift не имеет понятия о множествах. Используя
NSMutableSetв Swift может быть медленнее, чем с помощьюDictionary, который содержит пустые значения. Вы могли бы сделать это :var mySet: Dictionary<String, Boolean> = [:] mySet["something"]= 1затем просто повторите по клавишам.
Я построил обширный
Setтип похож на встроенныйArrayиDictionary- вот сообщения в блоге один и два и репозиторий GitHub:
extension Array where Element: Hashable { var setValue: Set<Element> { return Set<Element>(self) } } let numbers = [1,2,3,4,5,6,7,8,9,0,0,9,8,7] let uniqueNumbers = numbers.setValue // {0, 2, 4, 9, 5, 6, 7, 3, 1, 8} let names = ["John","Mary","Steve","Mary"] let uniqueNames = names.setValue // {"John", "Mary", "Steve"}
Я думал, что структура с внутренним словарем будет путь. Я только начал использовать его, поэтому он не завершен, и я еще не знаю о производительности.
struct Set<T : Hashable> { var _items : Dictionary<T, Bool> = [:] mutating func add(newItem : T) { _items[newItem] = true } mutating func remove(newItem : T) { _items[newItem] = nil } func contains(item: T) -> Bool { if _items.indexForKey(item) != nil { return true } else { return false } } var items : [T] { get { return [T](_items.keys) } } var count : Int { get { return _items.count } } }
вы на самом деле можете создать набор объектов довольно легко (в отличие от GoZoner, есть встроенный метод contains):
class Set<T : Equatable> { var items : T[] = [] func add(item : T) { if !contains(items, { == item}) { items += item } } }и вы, возможно, даже хотите объявить пользовательский оператор:
@assignment @infix func += <T : Equatable> (inout set : Set<T>, items : T[]) -> Set<T> { for item in items { set.add(item) } return set }
всегда в таком случае критическим фактором является то, как сравнивать объекты и какие типы объектов входят в набор. Использование Swift-словаря, где заданные объекты являются ключами словаря, может быть проблемой, основанной на ограничениях на тип ключа (String, Int, Double, Bool, valueless Enumerations или hashable).
если вы можете определить хэш-функцию на тип объекта, то вы можете использовать словарь. если объекты упорядочиваются, тогда вы может определить дерево. если объекты только сопоставимы с
==затем вам нужно будет перебирать элементы набора, чтобы обнаружить уже существующий объект.// When T is only Equatable class Set<T: Equatable> { var items = Array<T>() func hasItem (that: T) { // No builtin Array method of hasItem... // because comparison is undefined in builtin Array for this: T in items { if (this == that) { return true } } return false } func insert (that: T) { if (!hasItem (that)) items.append (that) } }выше приведен пример построения Swift
Set; в примере используются объекты, которые толькоEquatable- который, в то время как общий случай, не обязательно приводит к эффективномуSetреализации (O (N) сложность поиска - выше приведен пример).
поэтому я думаю, что создание набора с массивом-это ужасная идея - O (n) - это временная сложность этого набора.
Я собрал хороший набор, который использует словарь:https://github.com/evilpenguin/Swift-Stuff/blob/master/Set.swift
Я написал функцию для решения этой проблемы.
public func removeDuplicates<C: ExtensibleCollectionType where C.Generator.Element : Equatable>(aCollection: C) -> C { var container = C() for element in aCollection { if !contains(container, element) { container.append(element) } } return container }чтобы использовать его, просто передайте массив, который содержит повторяющиеся элементы для этой функции. И тогда он вернет массив с гарантией уникальности.
вы также можете передать
Dictionary,Stringили что-нибудь соответствуетExtensibleCollectionTypeпротокол, если хотите.
Comments