Какова производительность функции связывания массивов Swift высшего порядка? - PullRequest
0 голосов
/ 20 мая 2018

Я бы хотел связать фильтр, затем отобразить массив, но меня беспокоит производительность.я хотел бы понять, что компилятор swift достаточно умен, чтобы оптимизировать эту операцию, чтобы она выполнялась в одном цикле, а не в двух циклах, если бы я делал это следующим образом:

private func getSearchResponsesss(from bookResults: SearchBooks.Search.BookResults) -> SearchBooks.Search.Response {
    let presentableBooks = bookResults.books
        .filter { !$0.pictures.isEmpty }
        .map { book -> SearchBooks.Search.Response.BookPresentable in
            let image = book.pictures[0]
            let presentableBook = SearchBooks.Search.Response.BookPresentable(pictureKey: image,
                                                                              pictureStatus: .downloading,
                                                                              name: book.name,
                                                                              price: book.price)
            return presentableBook
        }
}

или мне следует делать какэто чтобы сэкономить на производительности?

private func getSearchResponsesss(from bookResults: SearchBooks.Search.BookResults) -> SearchBooks.Search.Response {
    var presentableBooks: [SearchBooks.Search.Response.BookPresentable] = []
    for book in bookResults.books {

        if book.pictures.isEmpty {
            continue
        }
        let image = book.pictures[0]
        let presentableBook = SearchBooks.Search.Response.BookPresentable(pictureKey: image,
                                                                          pictureStatus: .downloading,
                                                                          name: book.name,
                                                                          price: book.price)
        presentableBooks.append(presentableBook)
    }
    return presentableBooks
}

1 Ответ

0 голосов
/ 20 мая 2018

Компилятор недостаточно умен, чтобы понимать функции стандартной библиотеки и предлагать способы оптимизации их вызовов.

Однако проблема цепочки не в двойной итерации.С точки зрения производительности итерация не является большой проблемой.Настоящая проблема - последствия для памяти.Каждый раз, когда вы вызываете .filter или .map, результатом является новая последовательность, поэтому нам нужна память для хранения временной последовательности.

Чтобы слиться с этим, массивы Swift имеют .lazy свойство, которое позволяет лениво связывать, без создания промежуточных результатов и без нескольких итераций:

bookResults.books
    .lazy
    .filter { !$0.pictures.isEmpty }
    .map { ... }

В качестве другого решения вы всегда можете объединить filter и map, используя compactMap:

let presentableBooks = bookResults.books
    .compactMap { book in
        guard let image = book.pictures.first else { return nil }
        return SearchBooks.Search.Response.BookPresentable(
            pictureKey: image,                                                                             
            pictureStatus: .downloading,
            name: book.name,
            price: book.price
        )
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...