Get the next or previous item for an object in a collection or Swift array

What is the best way to identify an element preceding or following a specified object in a Swift array when protecting against errors outside?

+4
source share
2 answers

I suggest a simpler and more thorough implementation:

extension Collection where Iterator.Element: Equatable {
    typealias Element = Self.Iterator.Element

    func safeIndex(after index: Index) -> Index? {
        let nextIndex = self.index(after: index)
        return (nextIndex < self.endIndex) ? nextIndex : nil
    }

    func index(afterWithWrapAround index: Index) -> Index {
        return self.safeIndex(after: index) ?? self.startIndex
    }

    func item(after item: Element) -> Element? {
        return self.index(of: item)
            .flatMap(self.safeIndex(after:))
            .map{ self[$0] }
    }

    func item(afterWithWrapAround item: Element) -> Element? {
        return self.index(of: item)
            .map(self.index(afterWithWrapAround:))
            .map{ self[$0] }
    }
}

extension BidirectionalCollection where Iterator.Element: Equatable {
    typealias Element = Self.Iterator.Element

    func safeIndex(before index: Index) -> Index? {
        let previousIndex = self.index(before: index)
        return (self.startIndex <= previousIndex) ? previousIndex : nil
    }

    func index(beforeWithWrapAround index: Index) -> Index {
        return self.safeIndex(before: index) ?? self.index(before: self.endIndex)
    }

    func item(before item: Element) -> Element? {
        return self.index(of: item)
            .flatMap(self.safeIndex(before:))
            .map{ self[$0] }
    }


    func item(beforeWithWrapAround item: Element) -> Element? {
        return self.index(of: item)
            .map(self.index(beforeWithWrapAround:))
            .map{ self[$0] }
    }
}
+3
source

A good way to approach this is with an extension in Swift Array, or in this case a more generalized solution for all BidirectionalCollection objects, including arrays.

, , .

nil, , , , .

//
//  Array+Iterator.swift
//

extension BidirectionalCollection where Iterator.Element: Equatable {
    typealias Element = Self.Iterator.Element

    func after(_ item: Element, loop: Bool = false) -> Element? {
        if let itemIndex = self.index(of: item) {
            let lastItem: Bool = (index(after:itemIndex) == endIndex)
            if loop && lastItem {
                return self.first
            } else if lastItem {
                return nil
            } else {
                return self[index(after:itemIndex)]
            }
        }
        return nil
    }

    func before(_ item: Element, loop: Bool = false) -> Element? {
        if let itemIndex = self.index(of: item) {
            let firstItem: Bool = (itemIndex == startIndex)
            if loop && firstItem {
                return self.last
            } else if firstItem {
                return nil
            } else {
                return self[index(before:itemIndex)]
            }
        }
        return nil
    }
}

: , , :

let nextChild = children.after(jane)

, , , , :

let dishwasherTonight = children.after(sammy, loop: true)

, , , .


: endIndex :

, endIndex . - " ", .

+2

Source: https://habr.com/ru/post/1682360/


All Articles