Swift Language
Tablice
Szukaj…
Wprowadzenie
Składnia
- Array <Element> // Typ tablicy z elementami typu Element
- [Element] // Cukier syntaktyczny dla typu tablicy z elementami typu Element
- [element0, element1, element2, ... elementN] // Literał tablicowy
- [Element] () // Tworzy nową pustą tablicę typu [Element]
- Array (count: repeatValue :) // Tworzy tablicę elementów
count
, z których każdy jest inicjowany narepeatedValue
- Array (_ :) // Tworzy tablicę z dowolnej sekwencji
Uwagi
Tablice są uporządkowanym zbiorem wartości. Wartości mogą się powtarzać, ale muszą być tego samego typu.
Semantyka wartości
Kopiowanie tablicy spowoduje skopiowanie wszystkich elementów z oryginalnej tablicy.
Zmiana nowej tablicy nie zmieni oryginalnej tablicy.
var originalArray = ["Swift", "is", "great!"]
var newArray = originalArray
newArray[2] = "awesome!"
//originalArray = ["Swift", "is", "great!"]
//newArray = ["Swift", "is", "awesome!"]
Skopiowane tablice będą dzielić to samo miejsce w pamięci co oryginał, dopóki nie zostaną zmienione. W wyniku tego występuje obniżenie wydajności, gdy skopiowana tablica otrzymuje własne miejsce w pamięci, gdy jest zmieniana po raz pierwszy.
Podstawy tablic
Array
to uporządkowany typ kolekcji w standardowej bibliotece Swift. Zapewnia losowy dostęp O (1) i dynamiczną realokację. Tablica jest typem ogólnym , więc typ zawartych w niej wartości jest znany w czasie kompilacji.
Ponieważ Array
jest typem wartości , jej zmienność jest definiowana przez to, czy jest opisana jako var
( var
) czy let
(niezmienna).
Typ [Int]
(co oznacza: tablica zawierająca Int
s) to cukier składniowy dla Array<T>
.
Przeczytaj więcej o tablicach w Swift Programming Language .
Puste tablice
Następujące trzy deklaracje są równoważne:
// A mutable array of Strings, initially empty.
var arrayOfStrings: [String] = [] // type annotation + array literal
var arrayOfStrings = [String]() // invoking the [String] initializer
var arrayOfStrings = Array<String>() // without syntactic sugar
Tablice literałów
Literał tablicowy zapisywany jest za pomocą nawiasów kwadratowych otaczających elementy oddzielone przecinkami:
// Create an immutable array of type [Int] containing 2, 4, and 7
let arrayOfInts = [2, 4, 7]
Kompilator zwykle może wnioskować o typie tablicy na podstawie elementów literału, ale wyraźne adnotacje typu mogą zastąpić domyślną:
let arrayOfUInt8s: [UInt8] = [2, 4, 7] // type annotation on the variable
let arrayOfUInt8s = [2, 4, 7] as [UInt8] // type annotation on the initializer expression
let arrayOfUInt8s = [2 as UInt8, 4, 7] // explicit for one element, inferred for the others
Tablice z powtarzanymi wartościami
// An immutable array of type [String], containing ["Example", "Example", "Example"]
let arrayOfStrings = Array(repeating: "Example",count: 3)
Tworzenie tablic z innych sekwencji
let dictionary = ["foo" : 4, "bar" : 6]
// An immutable array of type [(String, Int)], containing [("bar", 6), ("foo", 4)]
let arrayOfKeyValuePairs = Array(dictionary)
Tablice wielowymiarowe
W Swift macierz wielowymiarowa jest tworzona przez zagnieżdżanie tablic: dwuwymiarowa tablica Int
to [[Int]]
(lub Array<Array<Int>>
).
let array2x3 = [
[1, 2, 3],
[4, 5, 6]
]
// array2x3[0][1] is 2, and array2x3[1][2] is 6.
Aby utworzyć wielowymiarową tablicę powtarzanych wartości, użyj zagnieżdżonych wywołań inicjalizatora tablicy:
var array3x4x5 = Array(repeating: Array(repeating: Array(repeating: 0,count: 5),count: 4),count: 3)
Dostęp do wartości macierzy
Poniższe przykłady wykorzystają tę tablicę do zademonstrowania dostępu do wartości
var exampleArray:[Int] = [1,2,3,4,5]
//exampleArray = [1, 2, 3, 4, 5]
Aby uzyskać dostęp do wartości o znanym indeksie, użyj następującej składni:
let exampleOne = exampleArray[2]
//exampleOne = 3
Uwaga: Wartość w indeksie drugim jest trzecią wartością w Array
. Array
używają indeksu zerowego, co oznacza, że pierwszy element w Array
ma indeks 0.
let value0 = exampleArray[0]
let value1 = exampleArray[1]
let value2 = exampleArray[2]
let value3 = exampleArray[3]
let value4 = exampleArray[4]
//value0 = 1
//value1 = 2
//value2 = 3
//value3 = 4
//value4 = 5
Uzyskaj dostęp do podzbioru Array
za pomocą filtra:
var filteredArray = exampleArray.filter({ $0 < 4 })
//filteredArray = [1, 2, 3]
Filtry mogą mieć złożone warunki, takie jak filtrowanie tylko liczb parzystych:
var evenArray = exampleArray.filter({ $0 % 2 == 0 })
//evenArray = [2, 4]
Można również zwrócić indeks danej wartości, zwracając nil
jeśli wartość nie została znaleziona.
exampleArray.indexOf(3) // Optional(2)
Istnieją metody dla pierwszej, ostatniej, maksymalnej lub minimalnej wartości w Array
. Te metody zwrócą nil
jeśli Array
jest pusta.
exampleArray.first // Optional(1)
exampleArray.last // Optional(5)
exampleArray.maxElement() // Optional(5)
exampleArray.minElement() // Optional(1)
Przydatne metody
Określ, czy tablica jest pusta, czy zwróć jej rozmiar
var exampleArray = [1,2,3,4,5]
exampleArray.isEmpty //false
exampleArray.count //5
Odwróć tablicę Uwaga: Wynik nie jest wykonywany w tablicy, w której wywoływana jest metoda, i musi zostać umieszczony we własnej zmiennej.
exampleArray = exampleArray.reverse()
//exampleArray = [9, 8, 7, 6, 5, 3, 2]
Modyfikowanie wartości w tablicy
Istnieje wiele sposobów dodawania wartości do tablicy
var exampleArray = [1,2,3,4,5]
exampleArray.append(6)
//exampleArray = [1, 2, 3, 4, 5, 6]
var sixOnwards = [7,8,9,10]
exampleArray += sixOnwards
//exampleArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
i usuń wartości z tablicy
exampleArray.removeAtIndex(3)
//exampleArray = [1, 2, 3, 5, 6, 7, 8, 9, 10]
exampleArray.removeLast()
//exampleArray = [1, 2, 3, 5, 6, 7, 8, 9]
exampleArray.removeFirst()
//exampleArray = [2, 3, 5, 6, 7, 8, 9]
Sortowanie tablicy
var array = [3, 2, 1]
Tworzenie nowej posortowanej tablicy
Ponieważ Array
jest zgodny z SequenceType
, możemy wygenerować nową tablicę posortowanych elementów za pomocą wbudowanej metody sortowania.
W Swift 2 odbywa się to za pomocą metody sort()
.
let sorted = array.sort() // [1, 2, 3]
Począwszy od Swift 3, zmieniono jego nazwę na sorted()
.
let sorted = array.sorted() // [1, 2, 3]
Sortowanie istniejącej tablicy na miejscu
Ponieważ Array
jest zgodny z MutableCollectionType
, możemy sortować jego elementy na miejscu.
W Swift 2 odbywa się to za pomocą metody sortInPlace()
.
array.sortInPlace() // [1, 2, 3]
Od Swift 3 zmieniono jego nazwę na sort()
.
array.sort() // [1, 2, 3]
Uwaga: Aby skorzystać z powyższych metod, elementy muszą być zgodne z protokołem
Comparable
.
Sortowanie tablicy za pomocą niestandardowego porządku
Możesz także posortować tablicę za pomocą zamknięcia, aby określić, czy jeden element powinien być uporządkowany przed drugim - co nie jest ograniczone do tablic, w których elementy muszą być Comparable
. Na przykład punkt Landmark
nie ma sensu Comparable
- ale nadal możesz sortować tablicę punktów orientacyjnych według wysokości lub nazwy.
struct Landmark {
let name : String
let metersTall : Int
}
var landmarks = [Landmark(name: "Empire State Building", metersTall: 443),
Landmark(name: "Eifell Tower", metersTall: 300),
Landmark(name: "The Shard", metersTall: 310)]
// sort landmarks by height (ascending)
landmarks.sortInPlace {$0.metersTall < $1.metersTall}
print(landmarks) // [Landmark(name: "Eifell Tower", metersTall: 300), Landmark(name: "The Shard", metersTall: 310), Landmark(name: "Empire State Building", metersTall: 443)]
// create new array of landmarks sorted by name
let alphabeticalLandmarks = landmarks.sort {$0.name < $1.name}
print(alphabeticalLandmarks) // [Landmark(name: "Eifell Tower", metersTall: 300), Landmark(name: "Empire State Building", metersTall: 443), Landmark(name: "The Shard", metersTall: 310)]
// sort landmarks by height (ascending)
landmarks.sort {$0.metersTall < $1.metersTall}
// create new array of landmarks sorted by name
let alphabeticalLandmarks = landmarks.sorted {$0.name < $1.name}
Uwaga: Porównanie ciągów może dać nieoczekiwane wyniki, jeśli ciągi są niespójne, patrz Sortowanie tablicy ciągów .
Przekształcanie elementów tablicy za pomocą mapy (_ :)
Ponieważ Array
jest zgodny z SequenceType
, możemy użyć map(_:)
aby przekształcić tablicę A
w tablicę B
za pomocą zwrócenia typu (A) throws -> B
Na przykład, możemy go użyć do przekształcenia tablicy Int
w tablicę String
s, tak jak to:
let numbers = [1, 2, 3, 4, 5]
let words = numbers.map { String($0) }
print(words) // ["1", "2", "3", "4", "5"]
map(_:)
wykona iterację w tablicy, stosując dane zamknięcie do każdego elementu. Wynik tego zamknięcia zostanie wykorzystany do zapełnienia nowej tablicy transformowanymi elementami.
Ponieważ String
ma inicjalizator, który otrzymuje Int
, możemy również użyć tej jaśniejszej składni:
let words = numbers.map(String.init)
Transformacja map(_:)
nie musi zmieniać typu tablicy - na przykład można jej również użyć do pomnożenia tablicy Int
przez dwa:
let numbers = [1, 2, 3, 4, 5]
let numbersTimes2 = numbers.map {$0 * 2}
print(numbersTimes2) // [2, 4, 6, 8, 10]
Wyodrębnianie wartości danego typu z tablicy za pomocą flatMap (_ :)
Tablica things
zawiera wartości Any
typu.
let things: [Any] = [1, "Hello", 2, true, false, "World", 3]
Możemy wyodrębnić wartości danego typu i utworzyć nową tablicę tego konkretnego typu. Powiedzmy, że chcemy wyodrębnić wszystkie Int(s)
i umieścić je w Int
Array w bezpieczny sposób.
let numbers = things.flatMap { $0 as? Int }
Teraz numbers
są zdefiniowane jako [Int]
. Funkcja flatMap
odrzuca wszystkie elementy nil
dlatego wynik zawiera tylko następujące wartości:
[1, 2, 3]
Filtrowanie tablicy
Możesz użyć metody filter(_:)
na SequenceType
, aby utworzyć nową tablicę zawierającą elementy sekwencji, które spełniają dany predykat, który można podać jako zakończenie .
Na przykład, filtrowanie liczb parzystych z [Int]
:
let numbers = [22, 41, 23, 30]
let evenNumbers = numbers.filter { $0 % 2 == 0 }
print(evenNumbers) // [22, 30]
Filtrowanie [Person]
, gdy jego wiek jest mniejszy niż 30:
struct Person {
var age : Int
}
let people = [Person(age: 22), Person(age: 41), Person(age: 23), Person(age: 30)]
let peopleYoungerThan30 = people.filter { $0.age < 30 }
print(peopleYoungerThan30) // [Person(age: 22), Person(age: 23)]
Filtrowanie zera z transformacji Array za pomocą flatMap (_ :)
Możesz użyć flatMap(_:)
w podobny sposób jak map(_:)
w celu utworzenia tablicy poprzez zastosowanie transformacji do elementów sekwencji.
extension SequenceType {
public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}
Różnica w stosunku do tej wersji flatMap(_:)
polega na tym, że oczekuje ona, że zamknięcie transformacji zwróci wartość opcjonalną T?
dla każdego z elementów. Następnie bezpiecznie rozpakuje każdą z tych opcjonalnych wartości, odfiltrowując nil
- co da tablicę [T]
.
Na przykład, może to w celu przekształcenia [String]
w [Int]
używając Int
failable „s String
inicjator , filtrowanie żadnych elementów, które nie mogą być zamienione:
let strings = ["1", "foo", "3", "4", "bar", "6"]
let numbersThatCanBeConverted = strings.flatMap { Int($0) }
print(numbersThatCanBeConverted) // [1, 3, 4, 6]
Możesz także użyć funkcji flatMap(_:)
do odfiltrowania wartości nil
, aby po prostu przekonwertować tablicę opcji na tablicę nie-opcji:
let optionalNumbers : [Int?] = [nil, 1, nil, 2, nil, 3]
let numbers = optionalNumbers.flatMap { $0 }
print(numbers) // [1, 2, 3]
Subskrybowanie tablicy za pomocą zakresu
Można wyciągnąć szereg kolejnych elementów z tablicy za pomocą zakresu.
let words = ["Hey", "Hello", "Bonjour", "Welcome", "Hi", "Hola"]
let range = 2...4
let slice = words[range] // ["Bonjour", "Welcome", "Hi"]
Subskrybowanie tablicy za pomocą zakresu zwraca ArraySlice
. To podsekwencja macierzy.
W naszym przykładzie mamy Array of Strings, więc ArraySlice<String>
.
Chociaż ArraySlice jest zgodny z CollectionType
i może być używany z sort
, filter
itp., Jego celem nie jest przechowywanie długoterminowe, ale obliczenia przejściowe: należy go przekonwertować z powrotem na macierz, jak tylko skończysz z nim pracować.
W tym celu użyj inicjatora Array()
:
let result = Array(slice)
Podsumowując w prostym przykładzie bez pośrednich kroków:
let words = ["Hey", "Hello", "Bonjour", "Welcome", "Hi", "Hola"]
let selectedWords = Array(words[2...4]) // ["Bonjour", "Welcome", "Hi"]
Grupowanie wartości tablic
Jeśli mamy taką strukturę
struct Box {
let name: String
let thingsInside: Int
}
oraz tablicę Box(es)
let boxes = [
Box(name: "Box 0", thingsInside: 1),
Box(name: "Box 1", thingsInside: 2),
Box(name: "Box 2", thingsInside: 3),
Box(name: "Box 3", thingsInside: 1),
Box(name: "Box 4", thingsInside: 2),
Box(name: "Box 5", thingsInside: 3),
Box(name: "Box 6", thingsInside: 1)
]
możemy pogrupować pola według właściwości thingsInside
, aby uzyskać Dictionary
którym key
jest liczba rzeczy, a wartością jest tablica pól.
let grouped = boxes.reduce([Int:[Box]]()) { (res, box) -> [Int:[Box]] in
var res = res
res[box.thingsInside] = (res[box.thingsInside] ?? []) + [box]
return res
}
Teraz zgrupowane jest [Int:[Box]]
i ma następującą treść
[
2: [Box(name: "Box 1", thingsInside: 2), Box(name: "Box 4", thingsInside: 2)],
3: [Box(name: "Box 2", thingsInside: 3), Box(name: "Box 5", thingsInside: 3)],
1: [Box(name: "Box 0", thingsInside: 1), Box(name: "Box 3", thingsInside: 1), Box(name: "Box 6", thingsInside: 1)]
]
Spłaszczanie wyniku transformacji Array za pomocą flatMap (_ :)
Oprócz możliwości utworzenia tablicy przez odfiltrowanie nil
z transformowanych elementów sekwencji, istnieje również wersja flatMap(_:)
która oczekuje, że zamknięcie transformacji zwróci sekwencję S
extension SequenceType {
public func flatMap<S : SequenceType>(transform: (Self.Generator.Element) throws -> S) rethrows -> [S.Generator.Element]
}
Każda sekwencja z transformacji zostanie połączona, w wyniku czego powstanie tablica zawierająca połączone elementy każdej sekwencji - [S.Generator.Element]
.
Łączenie znaków w tablicę ciągów
Na przykład możemy go użyć do pobrania tablicy ciągów pierwszych i połączenia ich znaków w jedną tablicę:
let primes = ["2", "3", "5", "7", "11", "13", "17", "19"]
let allCharacters = primes.flatMap { $0.characters }
// => "["2", "3", "5", "7", "1", "1", "1", "3", "1", "7", "1", "9"]"
Podział powyższego przykładu:
-
primes
to[String]
(Ponieważ tablica jest sekwencją, możemy wywołać na niejflatMap(_:)
). - Zamknięcie transformacji przyjmuje jeden z elementów
primes
,String
(Array<String>.Generator.Element
). - Zamknięcie następnie zwraca sekwencję typu
String.CharacterView
. - Wynikiem jest tablica zawierająca połączone elementy wszystkich sekwencji z każdego wywołania zamknięcia transformacji -
[String.CharacterView.Generator.Element]
.
Spłaszczanie tablicy wielowymiarowej
Ponieważ flatMap(_:)
połączy sekwencje zwrócone z wywołań transformacji, można go użyć do spłaszczenia tablicy wielowymiarowej - takiej jak tablica 2D w tablicę 1D, tablica 3D w tablicę 2D itp.
Można to zrobić po prostu zwracając podany element $0
(tablica zagnieżdżona) w zamknięciu:
// A 2D array of type [[Int]]
let array2D = [[1, 3], [4], [6, 8, 10], [11]]
// A 1D array of type [Int]
let flattenedArray = array2D.flatMap { $0 }
print(flattenedArray) // [1, 3, 4, 6, 8, 10, 11]
Sortowanie tablicy ciągów
Najprostszym sposobem jest użycie sorted()
:
let words = ["Hello", "Bonjour", "Salute", "Ahola"]
let sortedWords = words.sorted()
print(sortedWords) // ["Ahola", "Bonjour", "Hello", "Salute"]
lub sort()
var mutableWords = ["Hello", "Bonjour", "Salute", "Ahola"]
mutableWords.sort()
print(mutableWords) // ["Ahola", "Bonjour", "Hello", "Salute"]
Możesz przekazać zamknięcie jako argument do sortowania:
let words = ["Hello", "Bonjour", "Salute", "Ahola"]
let sortedWords = words.sorted(isOrderedBefore: { $0 > $1 })
print(sortedWords) // ["Salute", "Hello", "Bonjour", "Ahola"]
Alternatywna składnia z końcowym zamknięciem:
let words = ["Hello", "Bonjour", "Salute", "Ahola"]
let sortedWords = words.sorted() { $0 > $1 }
print(sortedWords) // ["Salute", "Hello", "Bonjour", "Ahola"]
Ale pojawią się nieoczekiwane wyniki, jeśli elementy w tablicy nie będą spójne:
let words = ["Hello", "bonjour", "Salute", "ahola"]
let unexpected = words.sorted()
print(unexpected) // ["Hello", "Salute", "ahola", "bonjour"]
Aby rozwiązać ten problem, albo posortuj małe wersje elementów:
let words = ["Hello", "bonjour", "Salute", "ahola"]
let sortedWords = words.sorted { $0.lowercased() < $1.lowercased() }
print(sortedWords) // ["ahola", "bonjour", "Hello", "Salute"]
Lub import Foundation
i użyj metod porównania NSString, takich jak caseInsensitiveCompare
:
let words = ["Hello", "bonjour", "Salute", "ahola"]
let sortedWords = words.sorted { $0.caseInsensitiveCompare($1) == .orderedAscending }
print(sortedWords) // ["ahola", "bonjour", "Hello", "Salute"]
Alternatywnie, użyj localizedCaseInsensitiveCompare
, który może zarządzać znakami diakrytycznymi.
Aby poprawnie posortować ciągi według wartości liczbowej, którą zawierają, użyj compare
z opcją .numeric
:
let files = ["File-42.txt", "File-01.txt", "File-5.txt", "File-007.txt", "File-10.txt"]
let sortedFiles = files.sorted() { $0.compare($1, options: .numeric) == .orderedAscending }
print(sortedFiles) // ["File-01.txt", "File-5.txt", "File-007.txt", "File-10.txt", "File-42.txt"]
Leniwie spłaszczając wielowymiarową tablicę za pomocą spłaszczania ()
Możemy użyć flatten()
, aby leniwie zmniejszyć zagnieżdżanie sekwencji wielowymiarowej.
Na przykład leniwe spłaszczanie tablicy 2D do tablicy 1D:
// A 2D array of type [[Int]]
let array2D = [[1, 3], [4], [6, 8, 10], [11]]
// A FlattenBidirectionalCollection<[[Int]]>
let lazilyFlattenedArray = array2D.flatten()
print(lazilyFlattenedArray.contains(4)) // true
W powyższym przykładzie funkcja flatten()
zwróci FlattenBidirectionalCollection
, która leniwie zastosuje spłaszczanie tablicy. Dlatego contains(_:)
będzie wymagał jedynie spłaszczenia pierwszych dwóch zagnieżdżonych tablic array2D
- ponieważ spowoduje to zwarcie po znalezieniu pożądanego elementu.
Łączenie elementów tablicy z redukcją (_: Połącz :)
Można reduce(_:combine:)
, aby połączyć elementy sekwencji w jedną wartość. Wynik przyjmuje wartość początkową, a także zamknięcie, które ma zastosowanie do każdego elementu - co zwróci nową skumulowaną wartość.
Możemy na przykład użyć go do zsumowania tablicy liczb:
let numbers = [2, 5, 7, 8, 10, 4]
let sum = numbers.reduce(0) {accumulator, element in
return accumulator + element
}
print(sum) // 36
Podajemy 0
do wartości początkowej, ponieważ jest to logiczna wartość początkowa dla sumowania. Gdybyśmy przekazali wartość N
, wynikowa sum
wynosiłaby N + 36
. Zamknięcie przekazane w celu reduce
ma dwa argumenty. accumulator
jest bieżącą zakumulowaną wartością, której przypisuje się wartość zwracaną przez zamknięcie przy każdej iteracji. element
jest bieżącym elementem w iteracji.
Jak w tym przykładzie, mijamy zamknięcie (Int, Int) -> Int
aby reduce
, co jest po prostu wynikiem dodania dwóch danych wejściowych - możemy faktycznie przekazać operator +
bezpośrednio, ponieważ operatory są funkcjami w Swift:
let sum = numbers.reduce(0, combine: +)
Usuwanie elementu z tablicy bez znajomości jego indeksu
Zasadniczo, jeśli chcemy usunąć element z tablicy, musimy znać jego indeks, abyśmy mogli go łatwo remove(at:)
za pomocą funkcji remove(at:)
.
Ale co, jeśli nie znamy indeksu, ale znamy wartość elementu do usunięcia!
Oto proste rozszerzenie tablicy, które pozwoli nam łatwo usunąć element z tablicy bez znajomości jego indeksu:
Swift3
extension Array where Element: Equatable {
mutating func remove(_ element: Element) {
_ = index(of: element).flatMap {
self.remove(at: $0)
}
}
}
na przykład
var array = ["abc", "lmn", "pqr", "stu", "xyz"]
array.remove("lmn")
print("\(array)") //["abc", "pqr", "stu", "xyz"]
array.remove("nonexistent")
print("\(array)") //["abc", "pqr", "stu", "xyz"]
//if provided element value is not present, then it will do nothing!
Również, jeśli przez pomyłkę zrobiliśmy coś takiego: array.remove(25)
tj. array.remove(25)
wartość o innym typie danych, kompilator zgłosi błąd, mówiąc:
cannot convert value to expected argument type
Znajdowanie minimalnego lub maksymalnego elementu tablicy
Możesz użyć minElement()
i maxElement()
, aby znaleźć minimum lub maksimum elementu w danej sekwencji. Na przykład z tablicą liczb:
let numbers = [2, 6, 1, 25, 13, 7, 9]
let minimumNumber = numbers.minElement() // Optional(1)
let maximumNumber = numbers.maxElement() // Optional(25)
Zwrócone wartości z tych metod są Opcjonalne, aby odzwierciedlić fakt, że tablica może być pusta - jeśli tak, to zwracane jest nil
.
Uwaga: powyższe metody wymagają, aby elementy były zgodne z protokołem
Comparable
.
Znalezienie minimalnego lub maksymalnego elementu za pomocą niestandardowego zamówienia
Możesz również użyć powyższych metod z niestandardowym zamknięciem , określając, czy jeden element powinien być zamówiony przed drugim, umożliwiając znalezienie minimalnego lub maksymalnego elementu w tablicy, w której elementy niekoniecznie są Comparable
.
Na przykład za pomocą tablicy wektorów:
struct Vector2 {
let dx : Double
let dy : Double
var magnitude : Double {return sqrt(dx*dx+dy*dy)}
}
let vectors = [Vector2(dx: 3, dy: 2), Vector2(dx: 1, dy: 1), Vector2(dx: 2, dy: 2)]
// Vector2(dx: 1.0, dy: 1.0)
let lowestMagnitudeVec2 = vectors.minElement { $0.magnitude < $1.magnitude }
// Vector2(dx: 3.0, dy: 2.0)
let highestMagnitudeVec2 = vectors.maxElement { $0.magnitude < $1.magnitude }
let lowestMagnitudeVec2 = vectors.min { $0.magnitude < $1.magnitude }
let highestMagnitudeVec2 = vectors.max { $0.magnitude < $1.magnitude }
Bezpieczny dostęp do indeksów
Dodając następujące rozszerzenie do indeksów tablicowych, można uzyskać dostęp bez wiedzy, czy indeks znajduje się w granicach.
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
przykład:
if let thirdValue = array[safe: 2] {
print(thirdValue)
}
Porównywanie 2 tablic z zamkiem
Funkcja zip
akceptuje 2 parametry typu SequenceType
i zwraca Zip2Sequence
gdzie każdy element zawiera wartość z pierwszej sekwencji i jeden z drugiej sekwencji.
Przykład
let nums = [1, 2, 3]
let animals = ["Dog", "Cat", "Tiger"]
let numsAndAnimals = zip(nums, animals)
nomsAndAnimals zawiera teraz następujące wartości
sekwencja 1 | sekwencja 1 |
---|---|
1 | "Dog" |
2 | "Cat" |
3 | "Tiger" |
Jest to przydatne, gdy chcesz wykonać pewnego rodzaju porównanie n-tego elementu każdej tablicy.
Przykład
Biorąc pod uwagę 2 tablice Int(s)
let list0 = [0, 2, 4]
let list1 = [0, 4, 8]
chcesz sprawdzić, czy każda wartość na list1
jest podwójną wartością list0
na list0
.
let list1HasDoubleOfList0 = !zip(list0, list1).filter { $0 != (2 * $1)}.isEmpty