快速设置为数组


186

一个NSSet可以被转换为Array使用set.allObjects(),但有在新的没有这样的方法Set(与夫特1.2引入)。仍然可以通过将Swift Set转换为NSSet并使用该allObjects()方法来完成,但这并不是最佳选择。

Answers:


351

您可以Set简单地使用给定Swift的所有元素创建一个数组

let array = Array(someSet)

之所以有效,是因为Set符合SequenceType协议,并且Array可以使用序列进行初始化。例:

let mySet = Set(["a", "b", "a"])  // Set<String>
let myArray = Array(mySet)        // Array<String>
print(myArray) // [b, a]

4
作为一个侧面说明,let array = Array(someSet)也适用于斯威夫特2
Suragch

...或者让myArray = myNSSet.allObjects作为![mySpecificType]
angelos.p 2015年

3
@plusangel:是的,如果NSSet给出了。问题是关于斯威夫特Set
马丁·R

@KendallHelmstetterGelner:我已经用Swift 2.3和Swift 3仔细检查了上面的代码示例。它按照我的预期进行编译和工作。你得到什么错误?
马丁R

@MartinR有趣的是,我正在尝试使用NSManagedObject关系中的集合进行操作,当时它不喜欢Array构造函数-虽然我现在尝试重现该问题,但现在还不能。我确实必须将“ arrayLiteral:”标签添加到Array构造函数中。我删除了之前的评论,因此不会混淆任何人,感谢您的检查!我不知道为什么Swift指南没有这种转换形式...
Kendall Helmstetter Gelner 16-10-26

21

在最简单的情况下,与斯威夫特3,你可以使用Arrayinit(_:)初始化得到一个ArraySetinit(_:)具有以下声明:

init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element

创建一个包含序列元素的数组。

用法:

let stringSet = Set(arrayLiteral: "car", "boat", "car", "bike", "toy")    
let stringArray = Array(stringSet)

print(stringArray)
// may print ["toy", "car", "bike", "boat"]

但是,如果你也想中的每个元素执行某些操作的Set同时,将其变成一个Array,你可以使用mapflatMapsortfilter和所提供的其他功能方法Collection的协议:

let stringSet = Set(["car", "boat", "bike", "toy"])
let stringArray = stringSet.sorted()

print(stringArray)
// will print ["bike", "boat", "car", "toy"]
let stringSet = Set(arrayLiteral: "car", "boat", "car", "bike", "toy") 
let stringArray = stringSet.filter { $0.characters.first != "b" }

print(stringArray)
// may print ["car", "toy"]
let intSet = Set([1, 3, 5, 2]) 
let stringArray = intSet.flatMap { String($0) }

print(stringArray)
// may print ["5", "2", "3", "1"]
let intSet = Set([1, 3, 5, 2])
// alternative to `let intArray = Array(intSet)`
let intArray = intSet.map { $0 }

print(intArray)
// may print [5, 2, 3, 1]

使用这种方法之一,我可以从可选集合中创建可选数组。
tzaloga

11

补充:

Swift没有Set和Dictionary的DEFINED ORDER。因此,您应该使用sorted()方法来防止出现意外结果,例如您的数组可以像[“ a”,“ b”]或[“ b”,“ a “],而您不想要这个。

解决此问题:

套装

var example:Set = ["a","b","c"]
let makeExampleArray = [example.sorted()]
makeExampleArray 

结果:[“ a”,“ b”,“ c”]

没有sorted()

有可能:

["a","b","c"] or ["b","c","a",] or ["c","a","b"] or ["a","c","b"] or ["b","a","c"] or ["c","b","a"] 

简单的数学:3!= 6


10

我创建了一个简单的扩展,为您提供了Swift 4.0中未排序Array的属性。Set

extension Set {
    var array: [Element] {
        return Array(self)
    }
}

如果要排序数组,则可以添加其他计算属性,也可以修改现有的属性以满足您的需要。

要使用此功能,只需致电

let array = set.array

3

Swift 2.x及更高版本的当前答案(来自有关集合类型的Swift编程语言指南)似乎是遍历Set条目,如下所示:

for item in myItemSet {
   ...
}

或者,使用“排序”方法:

let itemsArray = myItemSet.sorted()

似乎Swift设计师不喜欢allObjects作为访问机制,因为Set并不是真正有序的,因此他们想确保没有应用显式排序就不会出现数组。

如果您不需要排序的开销并且不关心顺序,那么我通常使用map或flatMap方法,它们提取数组应该更快一些:

let itemsArray = myItemSet.map { $0 }

它将构建一个Set持有的类型的数组,如果您需要将其变成特定类型的数组(例如,来自一组未声明为类型集的托管对象关系的权利),则可以执行以下操作:

var itemsArray : [MyObjectType] = []
if let typedSet = myItemSet as? Set<MyObjectType> {
 itemsArray = typedSet.map { $0 }
}

myItemSet.sorted()要求元素是Comparable。– myItemSet.map { $0 }应该产生与相同的结果Array(myItemSet),两者都通过枚举集合的所有元素来创建一个数组。后者对我仍然有效,您在上述评论中的一些细节将不胜感激。
Martin R

-2

调用此方法并传递您的设置

func getArrayFromSet(set:NSSet)-> NSArray {

return set.map ({ String($0) })
}

像这样 :

var letters:Set = Set<String>(arrayLiteral: "test","test") // your set
print(self.getArrayFromSet(letters))

2
使用阵列(<SET>)是一个更好的选择
塞巴斯蒂安REMY
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.