# Swift 的方式来使用数组

D2.jpg

GitHub地址

Array是在开发中最常用的数据类型之一，官方文档对Array的定义是：`An ordered, random-access collection.`。通常表示一个有序的集合，这里所说的有序并不是大小有序，而是指`Array`中元素的先后位置关系。

### 1、Swift的方式来操作数组

• 创建Array的N种方法
``````var testArray1: Array<Int> = Array<Int>()
var testArray2: [Int] = []
var testArray3 = [Int]()
var testArray4 = testArray3
``````

• 定义数组时同时指定初始值的方法
``````var testInts = [Int](repeating: 6, count: 3) // [6, 6, 6]
var sixInts = testInts + testInts // [6, 6, 6, 6, 6, 6]
``````
• countisEmtpy属性

`count`返回数组集合中元素的个数，类型是`Int`

``````let testArray = ["one","two","three","four","five","six"]
let countInts = testArray.count // 6
``````

`isEmpty`表示数组是否为空，类型是`Bool`再对数组操作前我们可以先判断数组是否为空再下一步操作

``````let testArray = ["one","two","three","four","five","six"]
if testArray.isEmpty == false {
let mapArray = testArray.map({ (mapString) -> String in
return mapString
})
} else {
print("数组为空")
}
``````
• 访问Array中的元素

• 通过索引访问数组的某个元素

``````let testArray = ["one","two","three","four","five","six"]
let sevenStr = testArray[7]
``````

• 访问数组中某个范围内的元素

`Swift`中我们可以通过使用`range operator`访问数组的一个范围,通过`range operator`方式得到的并不是一个`Array`,而是一个ArraySlice,官方文档`ArraySlice`的定义是`A slice of an`Array`,`ContiguousArray`, or`ArraySlice`instance.`通俗来说，就是`Array`某一段内容的`View`,不保存数组的内容，只保存这个`view`引用的数组的范围。我们可以通过这个`view`创建一个新的`Array`

``````let testArray = ["one","two","three","four","five","six"]
let rangeArray = Array(testArray[0...2])
``````
• 向数组中添加或删除元素

向数组的末尾添加元素，可以使用`append`方法, 或者使用`+=`的方式:

``````var testArray = ["one","two","three","four","five","six"]
testArray.append("seven") // ["one", "two", "three", "four", "five", "six", "seven"]
testArray += ["eight","nine"] // ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
``````

如果要在`Array`中间位置添加元素，可使用`insert`方法：

``````var testArray = ["one","three","four","five","six"]
testArray.insert("two", at: 1) // ["one","two","three","four","five","six"]
testArray.insert("seven", at: 7) // Thread 1: Fatal error: Array index is out of range`
``````

`insert`方法的第一个参数表示要插入的值，第二个参数表示要插入的位置索引，此处要注意的是：这个位置必须是一个合法的范围，即`0...array1.endIndex`,如果超出这个范围就会导致程序`Crash`

``````var testArray = ["one","two","three","four","five","six","seven"]
testArray.removeLast() // ["one","two","three","four","five","six"]
testArray.removeFirst() // ["two","three","four","five","six"]
testArray.remove(at: 7) // Fatal error: Index out of range
var secondTestArray = [String]()
secondTestArray.removeFirst() // Fatal error: Can't remove first element from an empty collection
secondTestArray.removeLast() // Fatal error: Can't remove last element from an empty collection
secondTestArray.popLast() // nil
``````

``````let testList = [1,2,3,4,5,6]
let oneIndex = testList.firstIndex { \$0 == 5 }
print("ondexIndex===============\(oneIndex ?? 0)")
``````
• 数组遍历

在开发中对`Array`每个元素的遍历也是常用操作:

• (1)、最简单的方式
``````let testArray = ["one","two","three","four","five","six"]
for vaule in testArray {
print(vaule)
}
``````
• (2)、遍历的时候，同时获得索引和值

使用数组对象的`enumerated()`方法，它会返回一个`Sequence`对象，包含了每个成员的索引和值。

`````` let testArray = ["one","two","three","four","five","six"]
for (index, value) in testArray.enumerated() {
print("\(index): \(value)")
}
``````
• (3)、通过闭包`closure`遍历

通过闭包`closure`，我们可以使用`Array``forEach`方法来遍历数组:

``````let testArray = ["one","two","three","four","five","six"]
testArray.forEach { (vaule) in
print(vaule)
}
``````

`for in``forEach`遍历的效果是一样的，但是如果使用`forEach`方法遍历数组就不能通过`break``continue`来退出循环，如果要退出遍历就只能使用`for in`方法。

``````testArray.forEach { (testChar) in
if testChar == "three" {
continue // 'continue' is only allowed inside a loop
}
}
``````
• (4)、map 、compactMap、 filter 遍历数组

``````let fractionArray: [Int] = [40,53,59,43,56,54,33,55,66,70,22,69]
var finallyList = [Int]()
for num in fractionArray {
finallyList.append(num + 30)
}// [70, 83, 89, 73, 86, 84, 63, 85, 96, 100, 52, 99]
``````

``````let fractionArray: [Int] = [40,53,59,43,56,54,33,55,66,70,22,69]
let finallyArray: [Int] = fractionArray.map {
return \$0 + 30
}
// [70, 83, 89, 73, 86, 84, 63, 85, 96, 100, 52, 99]
``````

`map`用于把数组中的所有元素按照指定规则操作变换并返回一个新的数组，这样比使用for循环更具表现力。

``````extension Array {
public func myselfMap<T>(_ transform: (Element) -> T) -> [T] {
var tmp: [T] = []
tmp.reserveCapacity(count)

for value in self {
tmp.append(transform(value))
}
return tmp
}
}
``````

compactMap方法是map的升级版,在遍历数组的同时，去除其中的nil值。

``````      let lsArray: [Int] = testList.compactMap { (num) -> Int? in
return num
} // [1, 2, 2, 3, 3, 4, 5, 6]
``````

````````` let excellentArray = finallyArray.filter {
\$0 >= 85
}// [89, 86, 85, 96, 100, 99]
```
``````

map在遍历数组的同时可以对每个参数做指定规则的操作，同时返回一个新的数组；
filter只按指定规则遍历数组，同时返回一个新的数组

`filter`是怎么实现的呢，我们可以根据`map`的实现方法来实现,其核心代码如下：

``````extension Array {
func myfilter(_ predicate: (Element) -> Bool) -> [Element] {
var tmp: [Element] = []
for value in self where predicate(value) {
tmp.append(value)
}
return tmp
}
}
``````
• (5)、min 、 max

``````finallyArray.min() // 52
finallyArray.max() // 100
``````
• `sorted``partition`对数组进行排序

``````let mixArray = finallyArray.sorted() // [52, 63, 70, 73, 83, 84, 85, 86, 89, 96, 99, 100]
let maxArray = finallyArray.sorted(by: >) // [100, 99, 96, 89, 86, 85, 84, 83, 73, 70, 63, 52]
``````
• 判断两个数组是否相等
``````finallyArray.elementsEqual(mixArray, by: {
\$0 == \$1
}) // false
``````
• 数组是否是以特定的排序开头

``````mixArray.starts(with: [100], by: {
\$0 == \$1
}) // true
``````
• 计算数组中元素和

``````var allNum = Int()
for num in finallyList {
allNum = allNum + num
}
allNum / (finallyList.count)
``````

`Swift`为开发者提供了更简单有效的方法：

``````finallyList.reduce(0, +) / (finallyList.count) // 81
``````
• 按条件把数组中的元素分类

``````let pass = mixArray.partition(by: {
\$0 > 60
})
let failedArray = mixArray[0 ..< pass] // 不及格的 [52]
let passArray = mixArray[pass ..< mixArray.endIndex] // 及格的 [63, 70, 73, 83, 84, 85, 86, 89, 96, 99, 100]
``````

### 2、Array和NSArray

• `Array` 是结构体，属于值类型, `NSArray` 是类，属于引用类型。

• `Array`是否可以被修改完全是通过`var``let`关键字来决定的，`Array`类型自身并不解决它是否可以被修改。

• `Array`如何转换为`NSArray`

• 赋值时内存

看下面两段代码

(1) 、 `Array``copy`

``````var testArray = ["one","two","three","four","five","six"]
let copyArray = testArray
testArray.append("seven") // ["one", "two", "three", "four", "five", "six", "seven"]
print(copyArray) // ["one", "two", "three", "four", "five", "six"]
``````

(2) 、 `NSArray``copy`

``````let mutArray = NSMutableArray(array: ["one","two","three","four","five","six"])
let copyArray: NSArray = mutArray
mutArray.insert("seven", at: 6) // ["one", "two", "three", "four", "five", "six", "seven"]
print(copyArray) // ["one", "two", "three", "four", "five", "six", "seven"]
``````

• 当我门使用`NSArray``NSMutableArray`时，`Swift`种的`var``let`关键字就不起作用了。

Apple developer Array