Array
聲明
@frozen struct Array<Element>
概述
數組是應用程序中最常用的數據類型之一。您使用數組來組織應用程序的數據。具體來說,您使用 Array
類型來保存單一類型的元素,即數組的 Element
類型。數組可以存儲任何類型的元素——從整數到字符串再到類。
Swift 使使用數組字麵量在代碼中創建數組變得很容易:隻需用方括號將逗號分隔的值列表括起來。在沒有任何其他信息的情況下,Swift 會創建一個包含指定值的數組,自動推斷數組的 Element
類型。例如:
// An array of 'Int' elements
let oddNumbers = [1, 3, 5, 7, 9, 11, 13, 15]
// An array of 'String' elements
let streets = ["Albemarle", "Brandywine", "Chesapeake"]
您可以通過在聲明中指定數組的Element
類型來創建一個空數組。例如:
// Shortened forms are preferred
var emptyDoubles: [Double] = []
// The full type name is also allowed
var emptyFloats: Array<Float> = Array()
如果您需要使用固定數量的默認值預初始化的數組,請使用 Array(repeating:count:)
初始化程序。
var digitCounts = Array(repeating: 0, count: 10)
print(digitCounts)
// Prints "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"
訪問數組值
當您需要對數組的所有元素執行操作時,請使用 for
- in
循環遍曆數組的內容。
for street in streets {
print("I don't live on \(street).")
}
// Prints "I don't live on Albemarle."
// Prints "I don't live on Brandywine."
// Prints "I don't live on Chesapeake."
使用isEmpty
屬性快速檢查數組是否有任何元素,或使用count
屬性查找數組中元素的數量。
if oddNumbers.isEmpty {
print("I don't know any odd numbers.")
} else {
print("I know \(oddNumbers.count) odd numbers.")
}
// Prints "I know 8 odd numbers."
使用 first
和 last
屬性可安全訪問數組的第一個和最後一個元素的值。如果數組為空,則這些屬性為 nil
。
if let firstElement = oddNumbers.first, let lastElement = oddNumbers.last {
print(firstElement, lastElement, separator: ", ")
}
// Prints "1, 15"
print(emptyDoubles.first, emptyDoubles.last, separator: ", ")
// Prints "nil, nil"
您可以通過下標訪問單個數組元素。非空數組的第一個元素始終位於索引零處。您可以使用從零到但不包括數組計數的任何整數為數組下標。使用等於或大於 count
的負數或索引會觸發運行時錯誤。例如:
print(oddNumbers[0], oddNumbers[3], separator: ", ")
// Prints "1, 7"
print(emptyDoubles[0])
// Triggers runtime error: Index out of range
添加和刪除元素
假設您需要存儲已注冊您正在教授的課程的學生姓名列表。在注冊期間,您需要在學生添加和刪除類時添加和刪除姓名。
var students = ["Ben", "Ivy", "Jordell"]
要將單個元素添加到數組的末尾,請使用 append(_:)
方法。通過將另一個數組或任何類型的序列傳遞給 append(contentsOf:)
方法,同時添加多個元素。
students.append("Maxime")
students.append(contentsOf: ["Shakia", "William"])
// ["Ben", "Ivy", "Jordell", "Maxime", "Shakia", "William"]
您可以通過對單個元素使用 insert(_:at:)
方法並使用 insert(contentsOf:at:)
從另一個集合或數組字麵量插入多個元素來在數組中間添加新元素。該索引和後麵的索引處的元素被移回以騰出空間。
students.insert("Liam", at: 3)
// ["Ben", "Ivy", "Jordell", "Liam", "Maxime", "Shakia", "William"]
要從數組中刪除元素,請使用 remove(at:)
、 removeSubrange(_:)
和 removeLast()
方法。
// Ben's family is moving to another state
students.remove(at: 0)
// ["Ivy", "Jordell", "Liam", "Maxime", "Shakia", "William"]
// William is signing up for a different class
students.removeLast()
// ["Ivy", "Jordell", "Liam", "Maxime", "Shakia"]
您可以通過將新值分配給下標來用新值替換現有元素。
if let i = students.firstIndex(of: "Maxime") {
students[i] = "Max"
}
// ["Ivy", "Jordell", "Liam", "Max", "Shakia"]
增加數組的大小
每個數組都會保留特定數量的內存來保存其內容。當您向數組添加元素並且該數組開始超出其保留容量時,該數組會分配更大的內存區域並將其元素複製到新存儲中。新存儲是舊存儲大小的倍數。這種指數增長策略意味著追加一個元素在恒定時間內發生,平均許多追加操作的性能。觸發重新分配的追加操作有性能成本,但隨著陣列變大,它們發生的頻率越來越低。
如果您知道大約需要存儲多少元素,請在追加到數組之前使用reserveCapacity(_:)
方法以避免中間重新分配。使用capacity
和count
屬性來確定數組可以存儲多少元素而不分配更大的存儲空間。
對於大多數Element
類型的數組,此存儲是一個連續的內存塊。對於 Element
類型為類或 @objc
協議類型的數組,此存儲可以是連續的內存塊或 NSArray
的實例。因為 NSArray
的任意子類都可以成為 Array
,所以在這種情況下不能保證表示或效率。
修改數組的副本
每個數組都有一個獨立的值,包括其所有元素的值。對於整數和其他結構等簡單類型,這意味著當您更改一個數組中的值時,該元素的值在數組的任何副本中都不會更改。例如:
var numbers = [1, 2, 3, 4, 5]
var numbersCopy = numbers
numbers[0] = 100
print(numbers)
// Prints "[100, 2, 3, 4, 5]"
print(numbersCopy)
// Prints "[1, 2, 3, 4, 5]"
如果數組中的元素是類的實例,則語義是相同的,盡管它們起初可能看起來不同。在這種情況下,存儲在數組中的值是對位於數組外部的對象的引用。如果您更改對一個數組中的對象的引用,則隻有該數組具有對新對象的引用。但是,如果兩個數組包含對同一個對象的引用,您可以從兩個數組中觀察到該對象屬性的變化。例如:
// An integer type with reference semantics
class IntegerReference {
var value = 10
}
var firstIntegers = [IntegerReference(), IntegerReference()]
var secondIntegers = firstIntegers
// Modifications to an instance are visible from either array
firstIntegers[0].value = 100
print(secondIntegers[0].value)
// Prints "100"
// Replacements, additions, and removals are still visible
// only in the modified array
firstIntegers[0] = IntegerReference()
print(firstIntegers[0].value)
// Prints "10"
print(secondIntegers[0].value)
// Prints "100"
與標準庫中的所有 variable-size 集合一樣,數組使用 copy-on-write 優化。陣列的多個副本共享相同的存儲,直到您修改其中一個副本。發生這種情況時,正在修改的陣列將其存儲替換為自身唯一擁有的副本,然後對其進行原地修改。有時會應用可以減少複製量的優化。
這意味著如果一個數組與其他副本共享存儲,則對該數組的第一次變異操作會產生複製該數組的成本。作為其存儲的唯一所有者的陣列可以就地執行變異操作。
在下麵的示例中,創建了一個numbers
數組以及共享同一存儲的兩個副本。當原始numbers
數組被修改時,它會在進行修改之前製作其存儲的唯一副本。對numbers
進行了進一步修改,而兩個副本繼續共享原始存儲。
var numbers = [1, 2, 3, 4, 5]
var firstCopy = numbers
var secondCopy = numbers
// The storage for 'numbers' is copied here
numbers[0] = 100
numbers[1] = 200
numbers[2] = 300
// 'numbers' is [100, 200, 300, 4, 5]
// 'firstCopy' and 'secondCopy' are [1, 2, 3, 4, 5]
Array 和 NSArray 之間的橋接
當您需要訪問需要 NSArray
實例而不是 Array
中的數據的 API 時,請使用 type-cast 運算符 (as
) 來橋接您的實例。為了使橋接成為可能,數組的 Element
類型必須是類、@objc
協議(從 Objective-C 導入的協議或標有 @objc
屬性的協議)或橋接到 Foundation 的類型類型。
以下示例顯示如何將Array
實例橋接到NSArray
以使用write(to:atomically:)
方法。在此示例中,colors
數組可以橋接到 NSArray
,因為 colors
數組的 String
元素橋接到 NSString
。另一方麵,編譯器會阻止橋接 moreColors
數組,因為它的 Element
類型是 Optional<String>
,它會將 not
橋接到 Foundation 類型。
let colors = ["periwinkle", "rose", "moss"]
let moreColors: [String?] = ["ochre", "pine"]
let url = URL(fileURLWithPath: "names.plist")
(colors as NSArray).write(to: url, atomically: true)
// true
(moreColors as NSArray).write(to: url, atomically: true)
// error: cannot convert value of type '[String?]' to type 'NSArray'
如果數組的元素已經是類或 @objc
協議的實例,則從 Array
橋接到 NSArray
需要 O(1) 時間和 O(1) 空間;否則,需要 O(n
) 時間和空間。
當目標數組的元素類型是類或@objc
協議時,從NSArray
橋接到Array
首先調用數組上的copy(with:)
(Objective-C中的- copyWithZone:
)方法來獲取不可變副本和然後執行額外的 Swift 簿記工作,需要 O(1) 時間。對於已經不可變的NSArray
的實例,copy(with:)
通常在 O(1) 時間內返回相同的數組;否則,複製性能未指定。如果 copy(with:)
返回相同的數組,則 NSArray
和 Array
的實例使用與 Array
的兩個實例共享存儲時使用的相同 copy-on-write 優化來共享存儲。
當目標數組的元素類型是橋接到 Foundation 類型的非類類型時,從 NSArray
橋接到 Array
會在 O(n
) 時間內將元素的橋接副本複製到連續存儲。例如,從NSArray
橋接到Array<Int>
會執行這樣的複製。訪問Array
實例的元素時不需要進一步的橋接。
可用版本
相關用法
- Swift Array enumerated()用法及代碼示例
- Swift ArraySlice starts(with:)用法及代碼示例
- Swift ArraySlice reduce(_:_:)用法及代碼示例
- Swift Array allSatisfy(_:)用法及代碼示例
- Swift Array removeFirst()用法及代碼示例
- Swift ArraySlice prefix(through:)用法及代碼示例
- Swift Array removeSubrange(_:)用法及代碼示例
- Swift ArraySlice prefix(upTo:)用法及代碼示例
- Swift Array max()用法及代碼示例
- Swift Array prefix(through:)用法及代碼示例
- Swift ArraySlice randomElement()用法及代碼示例
- Swift ArraySlice map(_:)用法及代碼示例
- Swift Array reduce(into:_:)用法及代碼示例
- Swift ArraySlice reversed()用法及代碼示例
- Swift Array sort()用法及代碼示例
- Swift ArraySlice append(contentsOf:)用法及代碼示例
- Swift Array suffix(_:)用法及代碼示例
- Swift Array dropLast(_:)用法及代碼示例
- Swift Array max(by:)用法及代碼示例
- Swift Array +=(_:_:)用法及代碼示例
- Swift ArraySlice removeSubrange(_:)用法及代碼示例
- Swift Array +(_:_:)用法及代碼示例
- Swift ArraySlice shuffled()用法及代碼示例
- Swift ArraySlice suffix(from:)用法及代碼示例
- Swift Array reverse()用法及代碼示例
注:本文由純淨天空篩選整理自apple.com大神的英文原創作品 Array。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。