Wie werden die ersten 5 Objekte von Array in Swift zurückgegeben?


178

Gibt es in Swift eine clevere Möglichkeit, die Methoden höherer Ordnung für Array zu verwenden, um die 5 ersten Objekte zurückzugeben? Die obj-c-Methode bestand darin, einen Index zu speichern und den inkrementierenden Index des Arrays bis zum Wert 5 zu durchlaufen und das neue Array zurückzugeben. Gibt es eine Möglichkeit, dies zu tun filter, mapoder reduce?


Siehe meine Antwort für Swift 4 , die bis zu 6 verschiedene Möglichkeiten zeigt, die ersten nElemente eines zurückzugeben Array.
Imanou Petit

Antworten:


440

Der mit Abstand beste Weg, um die ersten N Elemente eines Swift-Arrays zu erhalten, ist prefix(_ maxLength: Int):

let someArray = [1, 2, 3, 4, 5, 6, 7]
let first5 = someArray.prefix(5) // 1, 2, 3, 4, 5

Dies hat den Vorteil, dass die Grenzen sicher sind. Wenn die Anzahl, an die Sie übergeben, prefixgrößer als die Anzahl der Arrays ist, wird nur das gesamte Array zurückgegeben.

HINWEIS: Wie in den Kommentaren erwähnt, wird Array.prefixtatsächlich ein zurückgegeben ArraySlice, kein Array. In den meisten Fällen sollte dies keinen Unterschied machen. Wenn Sie das Ergebnis jedoch einem ArrayTyp zuweisen oder an eine Methode übergeben müssen, die einen ArrayParameter erwartet, müssen Sie das Ergebnis in einen ArrayTyp erzwingen :let first5 = Array(someArray.prefix(5))


41
+1 so eine schlechte Wahl, IMHO. Array hat dropFirstund dropLast, könnte genauso gut takeFirstund haben takeLast.
Mazyod

10
Auch wenn Sie first5ein Array sein müssen, schreiben let first5 = Array(someArray.prefix(5))
Sie

2
@mluisbrown Sorry, kann dir nicht zustimmen :) In meinem Projekt video = video.prefix(5)in Xcode 7.2 führt zu Kompilierungsfehler Cannot assign value of type 'ArraySlice<Video>' to type '[Video]'
ULazdins

5
video = Array(video.prefix(5))
Bartłomiej Semańczyk

2
@ onmyway133 prefixist möglicherweise nur Swift 2.x (ich erinnere mich nicht, ob es in 1.x war), aber es existiert sicherlich in jedem Betriebssystem, das Swift 2.x unterstützt, nämlich iOS 7 und höher. Die Verfügbarkeit von Swift-Funktionen wird durch Swift-Versionen bestimmt, nicht durch iOS-Versionen.
mluisbrown

99

Update: Es besteht jetzt die Möglichkeit prefix, die ersten n Elemente eines Arrays abzurufen. Überprüfen @ mluisbrown Antwort auf eine Erklärung , wie Präfix zu verwenden.

Original Antwort: Sie können es einfach ohne filter, mapoder reducenur um eine Reihe von Array Rückkehr:

var wholeArray = [1, 2, 3, 4, 5, 6]
var n = 5

var firstFive = wholeArray[0..<n] // 1,2,3,4,5

71
Wenn Sie nur die ersten nElemente aus einem Swift-Array möchten , können Sie dies tun, wholeArray.prefix(n)was den zusätzlichen Vorteil hat, dass die Grenzen sicher sind. Wenn ngrößer als das Array ist, wird prefixdas gesamte Array zurückgegeben.
mluisbrown

4
Es wird abstürzen, wenn das wholeArraynicht mehr Elemente hat alsn
Jake Lin

@Crashalot Ich bin mir nicht ganz sicher, aber ich denke zu der Zeit, als ich meine Antwort geschrieben habe, gab es so etwas nicht prefix.
Christian

1
Verwenden Sie diesen Code, um die ersten 5 Objekte zu erhalten ... Dies funktioniert perfekt [0,1,2,3,4,5] .enumerated (). FlatMap {$ 0 <5? $ 1: nil}
Manish Mahajan

64

Mit Swift 5 können Sie je nach Bedarf einen der 6 folgenden Spielplatzcodes auswählen , um Ihr Problem zu lösen.


# 1. Mit subscript(_:)Index

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array[..<5]
//let arraySlice = array[0..<5] // also works
//let arraySlice = array[0...4] // also works
//let arraySlice = array[...4] // also works
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

# 2. Mit prefix(_:)Methode

Komplexität: O (1) wenn die Sammlung übereinstimmt RandomAccessCollection; sonst O ( k ), wobei k die Anzahl der Elemente ist, die vom Beginn der Sammlung an ausgewählt werden sollen.

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(5)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

Apple sagt für prefix(_:):

Wenn die maximale Länge die Anzahl der Elemente in der Sammlung überschreitet, enthält das Ergebnis alle Elemente in der Sammlung.


#3. Mit prefix(upTo:)Methode

Komplexität: O (1)

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(upTo: 5)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

Apple sagt für prefix(upTo:):

Die Verwendung der prefix(upTo:)Methode entspricht der Verwendung eines halboffenen Bereichs als Index der Sammlung. Die tiefgestellte Notation wird gegenüber der Notation bevorzugt prefix(upTo:).


# 4. Mit prefix(through:)Methode

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let arraySlice = array.prefix(through: 4)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

# 5. Verwenden vonremoveSubrange(_:) Methode

Komplexität: O ( n ), wobei n die Länge der Sammlung ist.

var array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
array.removeSubrange(5...)
print(array) // prints: ["A", "B", "C", "D", "E"]

# 6. Verwenden vondropLast(_:) Methode

Komplexität: O (1) wenn die Sammlung übereinstimmt RandomAccessCollection; andernfalls O ( k ), wobei k die Anzahl der zu löschenden Elemente ist.

let array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
let distance = array.distance(from: 5, to: array.endIndex)
let arraySlice = array.dropLast(distance)
let newArray = Array(arraySlice)
print(newArray) // prints: ["A", "B", "C", "D", "E"]

28
let a: [Int] = [0, 0, 1, 1, 2, 2, 3, 3, 4]
let b: [Int] = Array(a.prefix(5))
// result is [0, 0, 1, 1, 2]

18

SWIFT 4

Eine andere Lösung:

Eine einfache Inline-Lösung, die nicht abstürzt, wenn Ihr Array zu kurz ist

[0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 3 ? $0.element : nil }

Funktioniert aber gut damit.

[0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 1000 ? $0.element : nil }

Normalerweise stürzt dies ab, wenn Sie dies tun:

[0,1,2,3,4,5].prefix(upTo: 1000) // THIS CRASHES

[0,1,2,3,4,5].prefix(1000) // THIS DOESNT

3
für swift3[0,1,2,3,4,5].enumerated().flatMap{ $0.offset < 1000 ? $0.element : nil }
StevenTsooo

1
Vielen Dank! Wenn Sie ein Update durchführen möchten, wird flatMap in Swift 4 jetzt als compactMap für die Array-Komprimierung bezeichnet.
Manmal

14

Um die ersten 5 Elemente eines Arrays zu erhalten, müssen Sie lediglich das betreffende Array in Scheiben schneiden. In Swift machen Sie es so:array[0..<5] .

Um die Auswahl der N ersten Elemente eines Arrays etwas funktionaler und verallgemeinerbarer zu gestalten, können Sie eine Erweiterungsmethode dafür erstellen. Zum Beispiel:

extension Array {
    func takeElements(var elementCount: Int) -> Array {
        if (elementCount > count) {
            elementCount = count
        }
        return Array(self[0..<elementCount])
    }
}

5

Ich habe Markus 'Antwort leicht geändert, um sie für die neueste Swift-Version zu aktualisieren, da varIhre Methodendeklaration nicht mehr unterstützt wird:

extension Array {
    func takeElements(elementCount: Int) -> Array {
        if (elementCount > count) {
            return Array(self[0..<count])
        }
        return Array(self[0..<elementCount])
    }
}

3

Swift 4

Um die ersten N Elemente eines Swift-Arrays zu erhalten, können Sie Folgendes verwenden prefix(_ maxLength: Int):

Array(largeArray.prefix(5))

1

Swift 4 mit gespeicherten Array-Typen

extension Array {
    func take(_ elementsCount: Int) -> [Element] {
        let min = Swift.min(elementsCount, count)
        return Array(self[0..<min])
    }
}

1

Update für Swift 4:

[0,1,2,3,4,5].enumerated().compactMap{ $0 < 10000 ? $1 : nil }

Für schnelle 3:

[0,1,2,3,4,5].enumerated().flatMap{ $0 < 10000 ? $1 : nil }

1
Unwirksame Lösung. 1) Sie erstellen eine zusätzliche Längenfolge eines Arrays. 2) Sie durchlaufen alle Elemente.
Alexander Bekert

2
10000? Was ist das?
BangOperator

1

Schlicht und einfach

extension Array {
    func first(elementCount: Int) -> Array {
          let min = Swift.min(elementCount, count)
          return Array(self[0..<min])
    }
}

1

Für ein Array von Objekten können Sie eine Erweiterung aus Sequence erstellen.

extension Sequence {
    func limit(_ max: Int) -> [Element] {
        return self.enumerated()
            .filter { $0.offset < max }
            .map { $0.element }
    }
}

Verwendung:

struct Apple {}

let apples: [Apple] = [Apple(), Apple(), Apple()]
let limitTwoApples = apples.limit(2)

// limitTwoApples: [Apple(), Apple()]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.