Разделить массив, затем отсортировать части по дате - PullRequest
0 голосов
/ 28 апреля 2020

Учитывая этот массив объектов:

struct Product {
    var isFresh: Bool
    var date: String
}

let products = [Product(isFresh: true, date: "2012-11-05T15:56+0000"),
                Product(isFresh: false, date: "2017-11-05T15:56+0000"),
                Product(isFresh: true, date: "2019-11-05T15:56+0000"),
                Product(isFresh: false, date: "2014-11-05T15:56+0000"),
                Product(isFresh: true, date: "2013-11-05T15:56+0000"),
]

Как я могу написать функцию, которая разделяет массив на две части (isFre sh &! IsFre sh), а затем сортирует две части по дате и поместите в верхнюю часть списка продукты, помеченные как isFre sh = true.

Я управляю первой частью:

private func handleProducts(_ products: [Product]) -> [Product] {

    return Dictionary(grouping: products) { $0.isFresh }
        .sorted(by: { $0.key < $1.key })
        .flatMap { $0.value }
}

Ответы [ 3 ]

0 голосов
/ 28 апреля 2020

Используйте filter и sorted(by:) дважды, чтобы получить массив из 2 массивов, а затем объедините их, используя flatMap

let fresh = [products.filter { $0.isFresh }.sorted(by: { $0.date < $1.date}), 
             products.filter { !$0.isFresh }.sorted(by: { $0.date < $1.date})]
            .flatMap {$0}
0 голосов
/ 28 апреля 2020

Если после группировки продуктов в словаре вы хотите отсортировать отдельные массивы продуктов для каждого из них, вы можете использовать mapValues, например:

let results = Dictionary(grouping: products) { $0.isFresh }
    .mapValues { $0.sorted { $0.date < $1.date } }           // sort the subarrays of products within freshness categories
    .sorted { $0.key && !$1.key }                            // sort by freshness
    .flatMap { $0.value }                                    // flatten the subarrays of products

(обратите внимание, вы используете $0.key < $1.key, но логические значения не имеют собственного порядка сортировки, поэтому я использовал шаблон $0.key && !$1.key.)

Но если вы действительно просто хотите получить плоский массив продуктов, сначала сортируйте по свежести, а затем date, я бы так и сделал:

let results = products.sorted {
    if $0.isFresh != $1.isFresh { return $0.isFresh }
    return $0.date < $1.date
}

Не связано, в то время как ваши строки дат сортируются, потому что их сортировка по алфавиту соответствует их хронологической сортировке, мы обычно используем Date вместо этого объекты исключают двусмысленность и не делают сортировку зависимой от конкретного строкового представления дат.

Поэтому я бы предложил сделать свойство date типом Date и использовать для форматирования даты преобразователь эти строки для Date объектов при заполнении этого массива Product объектов.

0 голосов
/ 28 апреля 2020

Сначала отсортируйте массив продуктов по дате

products.sort {
    $0.date > $1.date
}

Затем примените фильтр так, как вам требуется: -

let freshProductArr = products.filter {
    return $0.isFresh == true
}

let staleProductArr = products.filter {
    return $0.isFresh == false
}

Если вы хотите сохранить тот же массив: -

products.sort {
   ($0.date > $1.date)
}

products.sort {
     $0.isFresh && !$1.isFresh
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...