Bagaimana cara mengembalikan 5 objek pertama Array di Swift?

179

Dalam Swift, apakah ada cara pintar menggunakan metode urutan lebih tinggi pada Array untuk mengembalikan 5 objek pertama? Cara objektif melakukannya adalah menyimpan indeks, dan untuk-loop melalui indeks kenaikan array sampai 5 dan mengembalikan array baru. Apakah ada cara untuk melakukan ini filter, mapatau reduce?

bogen
sumber
Lihat jawaban saya untuk Swift 4 yang menunjukkan hingga 6 cara berbeda untuk mengembalikan nelemen pertama dari sebuah Array.
Imanou Petit

Jawaban:

446

Sejauh ini cara paling rapi untuk mendapatkan elemen N pertama dari array Swift adalah menggunakan prefix(_ maxLength: Int):

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

Ini memiliki manfaat menjadi batas aman. Jika jumlah yang Anda berikan prefixlebih besar dari jumlah array maka itu hanya mengembalikan seluruh array.

CATATAN: seperti yang ditunjukkan dalam komentar, Array.prefixsebenarnya mengembalikan sebuah ArraySlice, bukan sebuah Array. Dalam kebanyakan kasus ini seharusnya tidak membuat perbedaan tetapi jika Anda perlu menetapkan hasil ke suatu Arrayjenis atau meneruskannya ke metode yang mengharapkan Arrayparam Anda perlu memaksa hasilnya menjadi suatu Arrayjenis:let first5 = Array(someArray.prefix(5))

mluisbrown
sumber
42
Memberi +1 pilihan nama yang buruk, IMHO. Array memiliki dropFirstdan dropLast, mungkin juga memiliki takeFirstdan takeLast.
Mazyod
10
Juga jika Anda perlu first5sebuah array, cukup tulislet first5 = Array(someArray.prefix(5))
ULazdins
2
@mluisbrown Maaf, tidak dapat setuju dengan Anda :) Dalam proyek saya video = video.prefix(5)di Xcode 7.2 menghasilkan kesalahan kompilasi Cannot assign value of type 'ArraySlice<Video>' to type '[Video]'
ULazdins
5
video = Array(video.prefix(5))
Bartłomiej Semańczyk
2
@ onmyway133 prefixmungkin hanya Swift 2.x saja (saya tidak ingat apakah itu di 1.x), tetapi sudah pasti ada di OS yang mendukung Swift 2.x, yaitu iOS 7 ke atas. Ketersediaan fitur Swift ditentukan oleh rilis Swift, bukan versi iOS.
mluisbrown
99

Pembaruan: Sekarang ada kemungkinan untuk menggunakan prefixuntuk mendapatkan elemen pertama dari sebuah array. Periksa jawaban @ mluisbrown untuk penjelasan cara menggunakan awalan.

Jawaban Asli: Anda dapat melakukannya dengan sangat mudah tanpa filter, mapatau reducehanya dengan mengembalikan rentang array Anda:

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

var firstFive = wholeArray[0..<n] // 1,2,3,4,5
Kristen
sumber
71
Jika Anda ingin hanya nitem pertama dari array Swift yang dapat Anda lakukan wholeArray.prefix(n)yang memiliki manfaat tambahan sebagai batas aman. Jika nlebih besar dari ukuran array prefixmengembalikan seluruh array.
mluisbrown
4
Ini akan crash jika wholeArraytidak memiliki lebih banyak elemen darin
Jake Lin
@ Crashalot Saya tidak sepenuhnya yakin, tetapi saya pikir pada saat itu, di mana saya telah menulis jawaban saya, tidak ada yang namanya prefix.
Christian
1
Gunakan kode ini untuk mendapatkan 5 objek pertama ... Ini berfungsi dengan sempurna [0,1,2,3,4,5]. Enumerated (). FlatMap {$ 0 <5? $ 1: nihil}
Manish Mahajan
64

Dengan Swift 5, sesuai dengan kebutuhan Anda, Anda dapat memilih salah satu dari 6 kode Playground berikut untuk menyelesaikan masalah Anda.


# 1. Menggunakan subscript(_:)subskrip

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. Menggunakan prefix(_:)metode

Kompleksitas: O (1) jika koleksi sesuai dengan RandomAccessCollection; jika tidak, O ( k ), di mana k adalah jumlah elemen yang harus dipilih dari awal koleksi.

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"]

Negara Apple untuk prefix(_:):

Jika panjang maksimum melebihi jumlah elemen dalam koleksi, hasilnya berisi semua elemen dalam koleksi.


# 3. Menggunakan prefix(upTo:)metode

Kompleksitas: 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"]

Negara Apple untuk prefix(upTo:):

Menggunakan prefix(upTo:)metode ini setara dengan menggunakan rentang setengah terbuka sebagian sebagai subscript koleksi. Notasi subskrip lebih disukai daripada prefix(upTo:).


# 4 Menggunakan prefix(through:)metode

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 Menggunakan removeSubrange(_:)metode

Kompleksitas: O ( n ), di mana n adalah panjang koleksi.

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. Menggunakan dropLast(_:)metode

Kompleksitas: O (1) jika koleksi sesuai dengan RandomAccessCollection; jika tidak, O ( k ), di mana k adalah jumlah elemen untuk dijatuhkan.

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"]
Imanou Petit
sumber
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]
neoneye
sumber
18

SWIFT 4

Solusi berbeda:

Solusi inline mudah yang tidak akan macet jika array Anda terlalu pendek

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

Tetapi bekerja dengan baik dengan ini.

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

Biasanya ini akan macet jika Anda melakukan ini:

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

[0,1,2,3,4,5].prefix(1000) // THIS DOESNT
David Rees
sumber
3
untuk swift3[0,1,2,3,4,5].enumerated().flatMap{ $0.offset < 1000 ? $0.element : nil }
StevenTsooo
1
Terima kasih! Jika Anda ingin memperbarui, flatMap sekarang disebut compactMap di Swift 4 untuk pemadatan array.
manmal
14

Untuk mendapatkan 5 elemen pertama dari array, yang perlu Anda lakukan adalah mengiris array yang dimaksud. Dalam Swift, Anda melakukannya seperti ini: array[0..<5].

Untuk membuat memilih elemen N pertama dari array sedikit lebih fungsional dan dapat digeneralisasikan, Anda bisa membuat metode ekstensi untuk melakukannya. Misalnya:

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

Saya sedikit mengubah jawaban Markus untuk memperbaruinya untuk versi Swift terbaru, karena vardi dalam deklarasi metode Anda tidak lagi didukung:

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

Cepat 4

Untuk mendapatkan elemen N pertama dari array Swift, Anda dapat menggunakan prefix(_ maxLength: Int):

Array(largeArray.prefix(5))
unik
sumber
1

Swift 4 dengan menyimpan tipe array

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

Pembaruan untuk swift 4:

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

Untuk cepat 3:

[0,1,2,3,4,5].enumerated().flatMap{ $0 < 10000 ? $1 : nil }
mkkrolik
sumber
1
Solusi tidak efektif. 1) Anda membuat urutan panjang array tambahan. 2) Anda beralih melalui semua elemen.
Alexander Bekert
2
10000? Apa itu?
BangOperator
1

Polos & Sederhana

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

Untuk array objek, Anda dapat membuat ekstensi dari Sequence.

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

Pemakaian:

struct Apple {}

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

// limitTwoApples: [Apple(), Apple()]
Leo Valentim
sumber