Section 7/161 menit

7. Operator Transformasi dan Filtering

7. Operator Transformasi dan Filtering

compacted

Menghapus nil dari sequence optional — versi async dari compactMap { $0 }.

swift
// compacted: hilangkan nil dari stream
let rawValues: AsyncStream<Int?> = ...  // mungkin ada nil

for await value in rawValues.compacted() {
    // value dijamin non-nil di sini
    process(value)  // value: Int, bukan Int?
}

// Ekuivalen tapi lebih ekspresif dari:
for await value in rawValues.compactMap({ $0 }) {
    process(value)
}

removeDuplicates

Menghapus elemen berturut-turut yang sama — tidak menyimpan history semua elemen, hanya membandingkan dengan elemen sebelumnya.

swift
// removeDuplicates: hanya teruskan jika berbeda dari sebelumnya
let connectionState: AsyncStream<ConnectionState> = ...

for await state in connectionState.removeDuplicates() {
    // Tidak akan dapat .connected dua kali berturut-turut
    // Berguna untuk menghindari update UI yang tidak perlu
    updateConnectionIndicator(state)
}

// Dengan custom comparator
for await user in userStream.removeDuplicates(by: { $0.id == $1.id }) {
    // Hanya update jika ID berubah (bukan hanya reference)
    updateProfile(user)
}

adjacentPairs

Menghasilkan tuple dari dua elemen berturutan — berguna untuk menghitung selisih atau perubahan.

swift
// adjacentPairs: bandingkan nilai sekarang dengan sebelumnya
let stockPrices: AsyncStream<Double> = ...

for await (previous, current) in stockPrices.adjacentPairs() {
    let change = current - previous
    let percentChange = (change / previous) * 100
    print("Perubahan: \(String(format: "%.2f", percentChange))%")

    if abs(percentChange) > 5 {
        await sendAlert("Perubahan signifikan: \(percentChange)%")
    }
}

reductions

Versi async dari scan di Combine — menghasilkan nilai intermediate dari operasi reduce yang berjalan.

swift
// reductions: akumulasi running total
let transactions: AsyncStream<Double> = ...

for await runningTotal in transactions.reductions(0, +) {
    // emit: 100, 150, 220, 180, ...  (running total setelah setiap transaksi)
    updateBalanceDisplay(runningTotal)
}

// reductions dengan initial value terpisah
for await stats in sensorReadings.reductions(into: SensorStats()) { stats, reading in
    stats.count += 1
    stats.sum += reading.value
    stats.min = min(stats.min, reading.value)
    stats.max = max(stats.max, reading.value)
} {
    updateStatsDisplay(stats)
}

interspersed

Menyisipkan elemen di antara setiap elemen sequence.

swift
// interspersed: sisipkan separator
let words = ["Swift", "adalah", "bahasa", "modern"].async

for await word in words.interspersed(with: " ") {
    print(word, terminator: "")
    // Output: "Swift adalah bahasa modern"
}

// Berguna untuk separator UI (divider antar item)
let items = itemStream.interspersed(with: .divider)