Swift教程12-数组的结构体本质,对比NSArray

Swift中的数组要求在创建时其存储的类型是确定的,这点与Oc中的数组有一些不同;

当然,这也不是绝对的,因为有时候数组可以使用范型来约束其类型,只需遵循相应的协议即可,类型并不是完全一致的.

Swift中的数组相比于Oc的数组,功能更加强大;使用更加简便;当然也更加复杂了(光是Array的代码就有9800多行)


1.数组的本质,查看官方的API可以知道数组实际上是一个 结构体.


struct Array<T> : MutableCollectionType,Sliceable {

    /// The type of element stored by this `Array`
    typealias Element = T

    /// Always zero,which is the index of the first element when non-empty.
    var startIndex: Int { get }

    /// A "past-the-end" element index; the successor of the last valid
    /// subscript argument.
    var endindex: Int { get }
    subscript (index: Int) -> T

    /// Return a *generator* over the elements.
    ///
    /// Complexity: O(1)
    func generate() -> IndexingGenerator<[T]>

    /// A type that can represent a sub-range of an `Array` 
    typealias SubSlice = Slice<T>
    subscript (subRange: Range<Int>) -> Slice<T>

    /// Initialization from an existing buffer does not have "array.init"
    /// semantics because the caller may retain an alias to buffer.
    init(_ buffer: _ArrayBuffer<T>)
}


可以看到数组的构成包括:范型类型,计算属性,下标,构造器等



2.声明数组的两种方式


(1)使用范型(学过java的应该不会陌生)来约束数组的类型


方式;

var arr :Array<类型>

var arr : Array<Int>

(2) 符号简写方式定义数组变量


方式:

var arr :[类型]

var arr2 :[String]


(3)定义隐式的数组类型,自动推断


方式:


var arr3 = [数组元素1,元素2,.....]

var arr3 = [1,2,3]

上述的arr3不用声明类型,系统可以自动推断为 Int类型


3.数组的创建方式


(1)使用系统提供的init()构造器


使用示例:

arr = Array<Int>()

( 2)使用init(count: 10,repeatedValue:2) 创建一个 个数为 count的,重复值为 repeatedValue的数组


示例,创建一个 元素个数为10,重复值的值为2的数组


arr = Array<Int>(count: 10,repeatedValue: 2)

(3)使用直接赋值法


var arr3 = [1,3]



4.数组的几种遍历方式


(1)利用 数组的count属性来遍历,count是数组元素的个数;并且使用数组的下标来访问数组中的元素


var arr3 = [1,3]


for var i = 0;i<arr3.count;i++
{
    
    arr3[i]+=1
    print(arr3[i])
}


(2)使用for in快速遍历


for elem in arr3
{
    println(elem)
}

注意: elem认是 let常量类型的,不可修改 elem的值


5.数组的方法,数组这个结构体,通过拓展增加了很多方法:



extension Array {

    /// Construct an empty Array
    init()

    /// Construct from an arbitrary sequence with elements of type `T`
    init<S : SequenceType where T == T>(_ s: S)

    /// Construct a Array of `count` elements,each initialized to
    /// `repeatedValue`.
    init(count: Int,repeatedValue: T)

    /// How many elements the Array stores
    var count: Int { get }

    /// How many elements the `Array` can store without reallocation
    var capacity: Int { get }

    /// `true` if and only if the `Array` is empty
    var isEmpty: Bool { get }

    /// The first element,or `nil` if the array is empty
    var first: T? { get }

    /// The last element,or `nil` if the array is empty
    var last: T? { get }

    /// Reserve enough space to store minimumCapacity elements.
    ///
    /// PostCondition: `capacity >= minimumCapacity` and the array has
    /// mutable contiguous storage.
    ///
    /// Complexity: O(`count`)
    mutating func reserveCapacity(minimumCapacity: Int)

    /// Append newElement to the Array
    ///
    /// Complexity: amortized O(1) unless `self`'s storage is shared with another live array; O(`count`) if `self` does not wrap a bridged `NSArray`; otherwise the efficiency is unspecified.
    mutating func append(newElement: T)

    /// Append the elements of `newElements` to `self`.
    ///
    /// Complexity: O(*length of result*) 
    /// 
    mutating func extend<S : SequenceType where T == T>(newElements: S)

    /// Remove an element from the end of the Array in O(1).
    /// Requires: count > 0
    mutating func removeLast() -> T

    /// Insert `newElement` at index `i`.
    ///
    /// Requires: `i <= count`
    ///
    /// Complexity: O(\ `count`\ ).
    mutating func insert(newElement: T,atIndex i: Int)

    /// Remove and return the element at index `i`
    ///
    /// Invalidates all indices with respect to `self`.
    ///
    /// Complexity: O(\ `count`\ ).
    mutating func removeAtIndex(index: Int) -> T

    /// Remove all elements.
    ///
    /// Postcondition: `capacity == 0` iff `keepCapacity` is `false`.
    ///
    /// Complexity: O(\ `countElements(self)`\ ).
    mutating func removeAll(keepCapacity: Bool = default)

    /// Interpose `self` between each consecutive pair of `elements`,/// and concatenate the elements of the resulting sequence.  For
    /// example,`[-1,-2].join([[1,3],[4,5,6],[7,8,9]])`
    /// yields `[1,3,-1,-2,4,6,7,9]`
    func join<S : SequenceType where [T] == [T]>(elements: S) -> [T]

    /// Return the result of repeatedly calling `combine` with an
    /// accumulated value initialized to `initial` and each element of
    /// `self`,in turn,i.e. return
    /// `combine(combine(...combine(combine(initial,self[0]),/// self[1]),...self[count-2]),self[count-1])`.
    func reduce<U>(initial: U,combine: (U,T) -> U) -> U

    /// Sort `self` in-place according to `isOrderedBefore`.  Requires:
    /// `isOrderedBefore` induces a `strict weak ordering
    /// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
    /// over the elements.
    mutating func sort(isOrderedBefore: (T,T) -> Bool)

    /// Return a copy of `self` that has been sorted according to
    /// `isOrderedBefore`.  Requires: `isOrderedBefore` induces a
    /// `strict weak ordering
    /// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
    /// over the elements.
    func sorted(isOrderedBefore: (T,T) -> Bool) -> [T]

    /// Return an `Array` containing the results of calling
    /// `transform(x)` on each element `x` of `self`
    func map<U>(transform: (T) -> U) -> [U]

    /// A Array containing the elements of `self` in reverse order
    func reverse() -> [T]

    /// Return an `Array` containing the elements `x` of `self` for which
    /// `includeElement(x)` is `true`
    func filter(includeElement: (T) -> Bool) -> [T]
}


包括构造器,判空,排序,追加,移除等方法;方法使用简单,在此 只举一例:

使用append追加元素

var arr3 = [1,3]

arr3.append(4)
arr3.append(5)


for var i = 0;i<arr3.count;i++
{
    
    arr3[i]+=1
    print(arr3[i])
}


几点说明:

mutating func
这个 前缀,说明了该方法是可变的方法;原因是 数组 和Oc的数组,不一样;Swift中的数组是值类型的;在函数中的形参传入实参时,认传入的是函数的副本,而无法直接修该该实参;故而出了可变方法,需要在 func之前加上 mutating 关键字.


6.数组的重载运算符+=的妙用


使用数组重载的运算符 += 我们可以直接对可变的数组 (使用 var 修饰) 追加另一个数组(注意,不是单个的元素)进来;从而把两个数组合二为一


var arr3:Array<Int> = [1,3]

var arr4 = [6,8]

arr3 += arr4

for var i = 0;i<arr3.count;i++
{
    
    arr3[i]+=1
    print(arr3[i])
}

arr3 数组 合并了 arr4 数组



7.数组的范围下标.我们可以对数组的下标取一个范围来访问数组中的某个范围的元素

对于范围不太理解的详见前面的Swift教程

(1)

方法:


var  arr2 = arr1[a...b]
var arr2 = arr1[a..<b]

取 arr1数组中下标为 a到 b的 元素,作为一个数组,放入到 arr2数组中;

注意:下标的范围 不要超过 count -1;避免发生 数组越界.


(2)对某个范围下标进行元素批量替换.


我们可以直接使用数组的范围下标来替换对应数组的多个元素,并且不需要关心前后改变的元素个数是否相等.数组 自动改变个数.


var arr3 = [0,1,6]

arr3[0...1] = [8,8]

println(arr3)

输出:
[8,6]

我们把 arr3数组对应 下标为 0和 1的元素,替换为 4个8;前后元素不一致,但是 数组可以自动改变元素的个数,并且插入到指定的位置.


(3)利用范围下标,快速清空数组


使用:

//清空 数组中的所有元素



arr[0...arr.count-1] = []  

详细示例:


var arr3 = [0,8]

println("清空数组之前: 数组是  \(arr3)")

arr3[0...arr3.count-1] = []

println("清空数组之后,数组是  :\(arr3)")

输出:
清空数组之前: 数组是  [8,6]
清空数组之后,数组是  :[]

可以看到数组中元素个数为0了.


8.多维数组.


定义一个二维数组:


var arr:[[类型]]

或者


var arr:Array<Array<类型>>


var arr :[[Int]]

arr = [[1,[5,7]]

println(arr[0][1])


var arr2:Array<Array<String>>
arr2 = Array<Array<String>>()

arr2.insert(["第一个","'第二个"],atIndex: 0)

println(arr2)

所谓数组类似,需要类型写法需要嵌套


9.数组的复制与引用类型.


数组复制的规律:

如果数组内的元素是值类型的,如整型,那么数组复制时,会把源数组复制出元素的副本;

如果数组内的元素是引用类型的,如对象,那么 数组复制时,只是复制出元素的指针,修改该指针则也会修改源数组的内容.


复制的形式,很简单,可以直接 使用 等于=,赋值符号 = 即可;


(1)值类型的赋值:

var arr1 = [1,3]

var arr2 = arr1

arr2[0] = 3
println(arr2)
println(arr1)
输出:
[3,3]
[1,3]

说明,arr2的修改对 arr1是没有影响的,此数组的复制为值类型的复制;


(2)引用类型的数组复制


首先创建一个属性 aa的类A,并创建一个构造器


class A
{
    var aa:String
    init(aa:String)
    {
        self.aa = aa
    }
}


把 arr1复制给 arr2,然后,改变arr2的第一个元素的值
var arr1 = [A(aa:"aa1"),A(aa:"aa2")]
println(arr1[0].aa)
var arr2 = arr1
arr2[0].aa = "aa2来也"
println(arr1[0].aa)
println(arr2[0].aa)

输出:
aa1
aa2来也
aa2来也

可以看到,当修改 arr2的时候;arr1也被修改了.


Swift更多教程:http://www.jb51.cc/cata/272739

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...