Swift 语言提供ArraysSetsDictionaries三种基本的集合类型用来存储集合数据。数组(Arrays)是有序数据的集。集合(Sets)是无序无重复数据的集。字典(Dictionaries)是无序的键值对的集。

Swift 语言中的ArraysSetsDictionaries中存储的数据值类型必须明确。这意味着我们不能把不正确的数据类型插入其中。同时这也说明我们完全可以对取回值的类型非常自信。

注意:
Swift 的ArraysSetsDictionaries类型被实现为泛型集合。更多关于泛型类型和集合,参见 泛型章节。


集合的可变性

如果创建一个ArraysSetsDictionaries并且把它分配成一个变量,这个集合将会是可变的。这意味着我们可以在创建之后添加更多或移除已存在的数据项,或者改变集合中的数据项。如果我们把ArraysSetsDictionaries分配成常量,那么它就是不可变的,它的大小和内容都不能被改变。

注意:
在我们不需要改变集合的时候创建不可变集合是很好的实践。如此 Swift 编译器可以优化我们创建的集合。

数组(Arrays)

数组使用有序列表存储同一类型的多个值。相同的值可以多次出现在一个数组的不同位置中。

注意: Swift 的Array类型被桥接到Foundation中的NSArray类。 更多关于在FoundationCocoa中使用Array的信息,参见 Using Swift with Cocoa and Obejective-C 一书。


数组的简单语法

写 Swift 数组应该遵循像Array<Element>这样的形式,其中Element是这个数组中唯一允许存在的数据类型。我们也可以使用像[Element]这样的简单语法。尽管两种形式在功能上是一样的,但是推荐较短的那种,而且在本文中都会使用这种形式来使用数组。


创建一个空数组

我们可以使用构造语法来创建一个由特定数据类型构成的空数组:

varsomeInts=[Int]()
print("someIntsisoftype[Int]with\(someInts.count)items.")
//打印"someIntsisoftype[Int]with0items."

注意,通过构造函数的类型,someInts的值类型被推断为[Int]

或者,如果代码上下文中已经提供了类型信息,例如一个函数参数或者一个已经定义好类型的常量或者变量,我们可以使用空数组语句创建一个空数组,它的写法很简单:[](一对空方括号):

someInts.append(3)
//someInts现在包含一个Int值
someInts=[]
//someInts现在是空数组,但是仍然是[Int]类型的。

创建一个带有默认值的数组

Swift 中的Array类型还提供一个可以创建特定大小并且所有数据都被默认的构造方法。我们可以把准备加入新数组的数据项数量(count)和适当类型的初始值(repeatedValue)传入数组构造函数:

varthreeDoubles=[Double](count:3,repeatedValue:0.0)
//threeDoubles是一种[Double]数组,等价于[0.0,0.0,0.0]

通过两个数组相加创建一个数组

我们可以使用加法操作符(+)来组合两种已存在的相同类型数组。新数组的数据类型会被从两个数组的数据类型中推断出来:

varanotherThreeDoubles=Array(count:3,repeatedValue:2.5)
//anotherThreeDoubles被推断为[Double],等价于[2.5,2.5,2.5]

varsixDoubles=threeDoubles+anotherThreeDoubles
//sixDoubles被推断为[Double],等价于[0.0,2.5]

用字面量构造数组

我们可以使用字面量来进行数组构造,这是一种用一个或者多个数值构造数组的简单方法。字面量是一系列由逗号分割并由方括号包含的数值:

[value 1,value 2,value 3]

下面这个例子创建了一个叫做shoppingList并且存储String的数组:

varshoppingList:[String]=["Eggs","Milk"]
//shoppingList已经被构造并且拥有两个初始项。

shoppingList变量被声明为“字符串值类型的数组“,记作[String]。 因为这个数组被规定只有String一种数据结构,所以只有String类型可以在其中被存取。 在这里,shoppinglist数组由两个String值("Eggs""Milk")构造,并且由字面量定义。

注意:
Shoppinglist数组被声明为变量(var关键字创建)而不是常量(let创建)是因为以后可能会有更多的数据项被插入其中。


在这个例子中,字面量仅仅包含两个String值。匹配了该数组的变量声明(只能包含String的数组),所以这个字面量的分配过程可以作为用两个初始项来构造shoppinglist的一种方式。

由于 Swift 的类型推断机制,当我们用字面量构造只拥有相同类型值数组的时候,我们不必把数组的类型定义清楚。 shoppinglist的构造也可以这样写:

varshoppingList=["Eggs","Milk"]

因为所有字面量中的值都是相同的类型,Swift 可以推断出[String]shoppinglist中变量的正确类型。


访问和修改数组

我们可以通过数组的方法和属性来访问和修改数组,或者使用下标语法。

可以使用数组的只读属性count来获取数组中的数据项数量:

print("Theshoppinglistcontains\(shoppingList.count)items.")
//输出"Theshoppinglistcontains2items."(这个数组有2个项)

使用布尔值属性isEmpty作为检查count属性的值是否为 0 的捷径:

ifshoppingList.isEmpty{
print("Theshoppinglistisempty.")
}else{
print("Theshoppinglistisnotempty.")
}
//打印"Theshoppinglistisnotempty."(shoppinglist不是空的)

也可以使用append(_:)方法在数组后面添加新的数据项:

shoppingList.append("Flour")
//shoppingList现在有3个数据项,有人在摊煎饼

除此之外,使用加法赋值运算符(+=)也可以直接在数组后面添加一个或多个拥有相同类型的数据项:

shoppingList+=["BakingPowder"]
//shoppingList现在有四项了
shoppingList+=["ChocolateSpread","Cheese","Butter"]
//shoppingList现在有七项了

可以直接使用下标语法来获取数组中的数据项,把我们需要的数据项的索引值放在直接放在数组名称的方括号中:

varfirstItem=shoppingList[0]
//第一项是"Eggs"

注意:
第一项在数组中的索引值是0而不是1。 Swift 中的数组索引总是从零开始。

我们也可以用下标来改变某个已有索引值对应的数据值:

shoppingList[0]="Sixeggs"
//其中的第一项现在是"Sixeggs"而不是"Eggs"

还可以利用下标来一次改变一系列数据值,即使新数据和原有数据的数量是不一样的。下面的例子把"Chocolate Spread""Cheese",和"Butter"替换为"Bananas""Apples"

shoppingList[4...6]=["Bananas","Apples"]
//shoppingList现在有6项

注意:
不可以用下标访问的形式去在数组尾部添加新项。

调用数组的insert(_:atIndex:)方法来在某个具体索引值之前添加数据项:

shoppingList.insert("MapleSyrup",atIndex:0)
//shoppingList现在有7项
//"MapleSyrup"现在是这个列表中的第一项

这次insert(_:atIndex:)方法调用把值为"Maple Syrup"的新数据项插入列表的最开始位置,并且使用0作为索引值。

类似的我们可以使用removeAtIndex(_:)方法来移除数组中的某一项。这个方法把数组在特定索引值中存储的数据项移除并且返回这个被移除的数据项(我们不需要的时候就可以无视它):

letmapleSyrup=shoppingList.removeAtIndex(0)
//索引值为0的数据项被移除
//shoppingList现在只有6项,而且不包括MapleSyrup
//mapleSyrup常量的值等于被移除数据项的值"MapleSyrup"

注意:
如果我们试着对索引越界的数据进行检索或者设置新值的操作,会引发一个运行期错误。我们可以使用索引值和数组的count属性进行比较来在使用某个索引之前先检验是否有效。除了当count等于 0 时(说明这是个空数组),最大索引值一直是count - 1,因为数组都是零起索引。

数据项被移除后数组中的空出项会被自动填补,所以现在索引值为0的数据项的值再次等于"Six eggs"

firstItem=shoppingList[0]
//firstItem现在等于"Sixeggs"

如果我们只想把数组中的最后一项移除,可以使用removeLast()方法而不是removeAtIndex(_:)方法来避免我们需要获取数组的count属性。就像后者一样,前者也会返回被移除的数据项:

letapples=shoppingList.removeLast()
//数组的最后一项被移除了
//shoppingList现在只有5项,不包括Apples
//apples常量的值现在等于"Apples"字符串

数组的遍历

我们可以使用for-in循环来遍历所有数组中的数据项:

foriteminshoppingList{
print(item)
}
//Sixeggs
//Milk
//Flour
//BakingPowder
//Bananas

如果我们同时需要每个数据项的值和索引值,可以使用enumerate()方法来进行数组遍历。enumerate()返回一个由每一个数据项索引值和数据值组成的元组。我们可以把这个元组分解成临时常量或者变量来进行遍历:

for(index,value)inshoppingList.enumerate(){
print("Item\(String(index+1)):\(value)")
}
//Item1:Sixeggs
//Item2:Milk
//Item3:Flour
//Item4:BakingPowder
//Item5:Bananas

更多关于for-in循环的介绍请参见for 循环。


集合(Sets)

集合(Set)用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。

注意:
Swift的Set类型被桥接到Foundation中的NSSet类。
关于使用FoundationCocoaSet的知识,请看 Using Swift with Cocoa and Objective-C

集合类型的哈希值

一个类型为了存储在集合中,该类型必须是可哈希化的--也就是说,该类型必须提供一个方法来计算它的哈希值。一个哈希值是Int类型的,相等的对象哈希值必须相同,比如a==b,因此必须a.hashValue == b.hashValue

Swift 的所有基本类型(比如String,Int,DoubleBool)默认都是可哈希化的,可以作为集合的值的类型或者字典的键的类型。没有关联值的枚举成员值(在枚举有讲述)默认也是可哈希化的。

注意:
你可以使用你自定义的类型作为集合的值的类型或者是字典的键的类型,但你需要使你的自定义类型符合 Swift 标准库中的Hashable协议。符合Hashable协议的类型需要提供一个类型为Int的可读属性hashValue。由类型的hashValue属性返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。

因为Hashable协议符合Equatable协议,所以符合该协议的类型也必须提供一个"是否相等"运算符(==)的实现。这个Equatable协议要求任何符合==实现的实例间都是一种相等的关系。也就是说,对于a,b,c三个值来说,==的实现必须满足下面三种情况:

  • a == a(自反性)

  • a == b意味着b == a(对称性)

  • a == b && b == c意味着a == c(传递性)

关于符合协议的更多信息,请看协议。


集合类型语法

Swift 中的Set类型被写为Set<Element>,这里的Element表示Set中允许存储的类型,和数组不同的是,集合没有等价的简化形式。


创建和构造一个空的集合

你可以通过构造器语法创建一个特定类型的空集合:

varletters=Set<Character>()
print("lettersisoftypeSet<Character>with\(letters.count)items.")
//打印"lettersisoftypeSet<Character>with0items."

注意:
通过构造器,这里的letters变量的类型被推断为Set<Character>

此外,如果上下文提供了类型信息,比如作为函数的参数或者已知类型的变量或常量,我们可以通过一个空的数组字面量创建一个空的Set

letters.insert("a")
//letters现在含有1个Character类型的值
letters=[]
//letters现在是一个空的Set,但是它依然是Set<Character>类型

用数组字面量创建集合

你可以使用数组字面量来构造集合,并且可以使用简化形式写一个或者多个值作为集合元素。

下面的例子创建一个称之为favoriteGenres的集合来存储String类型的值:

varfavoriteGenres:Set<String>=["Rock","Classical","Hiphop"]
//favoriteGenres被构造成含有三个初始值的集合

这个favoriteGenres变量被声明为“一个String值的集合”,写为Set<String>。由于这个特定的集合含有指定String类型的值,所以它只允许存储String类型值。这里的favoriteGenres变量有三个String类型的初始值("Rock""Classical""Hip hop"),并以数组字面量的方式出现。

注意:
favoriteGenres被声明为一个变量(拥有var标示符)而不是一个常量(拥有let标示符),因为它里面的元素将会在下面的例子中被增加或者移除。

一个Set类型不能从数组字面量中被单独推断出来,因此Set类型必须显式声明。然而,由于 Swift 的类型推断功能,如果你想使用一个数组字面量构造一个Set并且该数组字面量中的所有元素类型相同,那么你无须写出Set的具体类型。favoriteGenres的构造形式可以采用简化的方式代替:

varfavoriteGenres:Set=["Rock","Hiphop"]

由于数组字面量中的所有元素类型相同,Swift 可以推断出Set<String>作为favoriteGenres变量的正确类型。


访问和修改一个集合

你可以通过Set的属性和方法来访问和修改一个Set

为了找出一个Set中元素的数量,可以使用其只读属性count

print("Ihave\(favoriteGenres.count)favoritemusicgenres.")
//打印"Ihave3favoritemusicgenres."
print("Ihave\(favoriteGenres.count)favoritemusicgenres.")
//打印"Ihave3favoritemusicgenres."

使用布尔属性isEmpty作为一个缩写形式去检查count属性是否为0

iffavoriteGenres.isEmpty{
print("Asfarasmusicgoes,I'mnotpicky.")
}else{
print("Ihaveparticularmusicpreferences.")
}
//打印"Ihaveparticularmusicpreferences."

你可以通过调用Setinsert(_:)方法来添加一个新元素:

favoriteGenres.insert("Jazz")
//favoriteGenres现在包含4个元素

你可以通过调用Setremove(_:)方法去删除一个元素,如果该值是该Set的一个元素则删除该元素并且返回被删除的元素值,否则如果该Set不包含该值,则返回nil。另外,Set中的所有元素可以通过它的removeAll()方法删除。

ifletremovedGenre=favoriteGenres.remove("Rock"){
print("\(removedGenre)?I'moverit.")
}else{
print("Inevermuchcaredforthat.")
}
//打印"Rock?I'moverit."

使用contains(_:)方法去检查Set中是否包含一个特定的值:

iffavoriteGenres.contains("Funk"){
print("Igetuponthegoodfoot.")
}else{
print("It'stoofunkyinhere.")
}
//打印"It'stoofunkyinhere."

遍历一个集合

你可以在一个for-in循环中遍历一个Set中的所有值。

forgenreinfavoriteGenres{
print("\(genre)")
}
//Classical
//Jazz
//Hiphop

Swift 的Set类型没有确定的顺序,为了按照特定顺序来遍历一个Set中的值可以使用sort()方法,它将根据提供的序列返回一个有序集合.

forgenreinfavoriteGenres.sort(){
print("\(genre)")
}
//prints"Classical"
//prints"Hiphop"
//prints"Jazz

集合操作

你可以高效地完成Set的一些基本操作,比如把两个集合组合到一起,判断两个集合共有元素,或者判断两个集合是否全包含,部分包含或者不相交。


基本集合操作

下面的插图描述了两个集合-ab-以及通过阴影部分的区域显示集合各种操作的结果。

  • 使用intersect(_:)方法根据两个集合中都包含的值创建的一个新的集合。

  • 使用exclusiveOr(_:)方法根据在一个集合中但不在两个集合中的值创建一个新的集合。

  • 使用union(_:)方法根据两个集合的值创建一个新的集合。

  • 使用subtract(_:)方法根据不在该集合中的值创建一个新的集合。

letoddDigits:Set=[1,3,5,7,9]
letevendigits:Set=[0,2,4,6,8]
letsingleDigitPrimeNumbers:Set=[2,7]

oddDigits.union(evendigits).sort()
//[0,1,8,9]
oddDigits.intersect(evendigits).sort()
//[]
oddDigits.subtract(singleDigitPrimeNumbers).sort()
//[1,9]
oddDigits.exclusiveOr(singleDigitPrimeNumbers).sort()
//[1,9]

集合成员关系和相等

下面的插图描述了三个集合-a,bc,以及通过重叠区域表述集合间共享的元素。集合a是集合b的父集合,因为a包含了b中所有的元素,相反的,集合b是集合a的子集合,因为属于b的元素也被a包含。集合b和集合c彼此不关联,因为它们之间没有共同的元素。

  • 使用“是否相等”运算符(==)来判断两个集合是否包含全部相同的值。

  • 使用isSubsetof(_:)方法来判断一个集合中的值是否也被包含在另外一个集合中。

  • 使用isSupersetof(_:)方法来判断一个集合中包含另一个集合中所有的值。

  • 使用isstrictSubsetof(_:)或者isstrictSupersetof(_:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。

  • 使用isdisjointWith(_:)方法来判断两个集合是否不含有相同的值(是否没有交集)。

lethouseAnimals:Set=["

swift官方推荐翻译文档之集合类型的更多相关文章

  1. html5使用canvas实现弹幕功能示例

    这篇文章主要介绍了html5使用canvas实现弹幕功能示例的相关资料,需要的朋友可以参考下

  2. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. 前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)

    这篇文章主要介绍了前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. H5 canvas实现贪吃蛇小游戏

    本篇文章主要介绍了H5 canvas实现贪吃蛇小游戏,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

  6. ios – 声明NSDictionary并在Swift中添加键值对?

    我一直在尝试使用类类型键和值来声明一个NSDictionary,如下所示:这里,“Category”和“SubCategory”是全局类.我知道我不能将类类型用于关键字段.但是,无论如何,我应该做到这一点.有没有办法做到这一点?如何声明专门的NSDictionary或类似的东西来做到这一点?

  7. ios – parse.com用于键,预期字符串的无效类型,但是得到了数组

    我尝试将我的数据保存到parse.com.我已经预先在parse.com上创建了一个名为’SomeClass’的类.它有一个名为’mySpecialColumn’的列,其数据类型为String.这是我尝试使用以下代码保存数据的代码:如果我运行这个我得到:错误:密钥mySpecialColumn的无效类型,预期字符串,但得到数组这就是我在parse.com上的核心外观:有谁知道我为什么会收到这个错误?

  8. ios – 在Swift中将输入字段字符串转换为Int

    所以我非常擅长制作APP广告Swift,我试图在文本字段中做一些非常简单的输入,取值,然后将它们用作Int进行某些计算.但是’vardistance’有些东西不正确它是导致错误的最后一行代码.它说致命错误:无法解开Optional.None解决方法在你的例子中,距离是一个Int?否则称为可选的Int..toInt()返回Int?因为从String到Int的转换可能失败.请参阅以下示例:

  9. ios – Swift相当于`[NSDictionary initWithObjects:forKeys:]`

    Swift的原生字典是否与[NSDictionaryinitWithObjects:forKeys:]相当?假设我有两个带键和值的数组,并希望将它们放在字典中.在Objective-C中,我这样做:当然我可以通过两个数组迭代一个计数器,使用vardict:[String:Int]并逐步添加东西.但这似乎不是一个好的解决方案.使用zip和enumerate可能是同时迭代两者的更好方法.然而,这种方法

  10. 如何在iOS中检测文本(字符串)语言?

    例如,给定以下字符串:我想检测每个声明的字符串中使用的语言.让我们假设已实现函数的签名是:如果没有检测到语言,则返回可选字符串.因此,适当的结果将是:有一个简单的方法来实现它吗?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部