Как отсортировать и отфильтровать массив на основе другого массива? - PullRequest
0 голосов
/ 03 июля 2019

Как я могу отфильтровать и отсортировать listOfFruits по другой стране и сохранить его в listOfFilterAndSortedFruits?

Например: Если я выберу Canada с listOfFruit: ["Cherries", "Peer", "Cherries", "Apple"] и listOfFilterAndSortedFruits будет

var listOfFilterAndSortedFruits:[Fruit] = [
    Fruit(name: "Cherries", taste: "Juicy"),
    Fruit(name: "Peer", taste: "Sweat"),
    Fruit(name: "Cherries", taste: "Juicy"),
    Fruit(name: "Apple", taste: "Sweat")
]
class Fruit {
    var name: String
    var taste: String

    init(name: String, taste: String) {
        self.name = name
        self.taste = taste
    }
}

class Country {
    var name: String
    var listOfFruit: [String]

    init(name: String, listOfFruit: [String]) {
        self.name = name
        self.listOfFruit = listOfFruit
    }
}

var listOfFruits:[Fruit] = [
    Fruit(name: "Apple", taste: "Sweat"),
    Fruit(name: "Orange", taste: "Tart"),
    Fruit(name: "Cherries", taste: "Juicy"),
    Fruit(name: "Banana", taste: "Sweet"),
    Fruit(name: "Carambola", taste: "Tart"),
    Fruit(name: "Peer", taste: "Sweat"),
]

var listOfCountries:[Country] = [
    Country(name: "USA", listOfFruit: ["Apple", "Orange", "Cherries"]),
    Country(name: "Brazil", listOfFruit: ["Orange", "Banana", "Peer", "Carambola"]),
    Country(name: "Canada", listOfFruit: ["Cherries", "Peer", "Cherries", "Apple"]),
]

let listOFFruitInCanada = ["Cherries", "Peer", "Cherries", "Apple"]
var listOfFilterAndSortedFruits = [Fruit]()

Ответы [ 3 ]

0 голосов
/ 03 июля 2019

Вы используете массив фруктов:

let listOfFruits = [
    Fruit(name: "Apple", taste: "Sweet"),
    Fruit(name: "Orange", taste: "Tart"),
    Fruit(name: "Cherries", taste: "Juicy"),
    Fruit(name: "Banana", taste: "Sweet"),
    Fruit(name: "Carambola", taste: "Tart"),
    Fruit(name: "Pear", taste: "Sweet"),
]

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

Вместо этого вы можете использовать словарь.

Например, вы можете создать его из listOfFruits:

let fruitDictionary = Dictionary(grouping: listOfFruits) { $0.name }

Или, если этот listOfFruits только для поискаВначале вы можете просто определить его как словарь и пропустить этот шаг «преобразования массива в словарь».

Независимо от того, что дан массив имен канадских фруктов:

let listOfFruitNamesInCanada = ["Cherries", "Pear", "Cherries", "Apple"]

Если выЕсли вам нужен соответствующий массив Fruit объектов, теперь вы можете искать в словаре Fruit экземпляров:

let listOfFruitsInCanada = listOfFruitNamesInCanada.compactMap { fruitDictionary[$0] }

В результате:

[
    [Fruit(name: "Cherries", taste: "Juicy")], 
    [Fruit(name: "Pear", taste: "Sweet")], 
    [Fruit(name: "Cherries", taste: "Juicy")], 
    [Fruit(name: "Apple", taste: "Sweet")]
]

Ключ на выносзаключается в том, что я не сканирую массив с помощью listOfFruits.first(where: ...) (потому что он должен повторно сканировать массив для каждого фрукта, который мы ищем, с итоговой сложностью O(n)).Вместо этого я использую словарь fruitDictionary[...] (в котором мы можем сразу найти нужный объект Fruit со сложностью O(1)).


Не связано, но вы можете рассмотреть возможность использования struct типов:

struct Fruit {
    let name: String
    let taste: String
}

struct Country {
    let name: String
    let listOfFruit: [String]
}

Вы можете использовать свои class ссылочные типы, если вы действительно этого хотите, но в настоящее время мы склонны использовать struct типов значений.

0 голосов
/ 03 июля 2019

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

getSortedFriutListForCountry метод выдаст отсортированный список фруктов для названия страны, если страна с таким именем существует.

var listOfFruits:[Fruit] = [
    Fruit(name: "Apple", taste: "Sweat"),
    Fruit(name: "Orange", taste: "Tart"),
    Fruit(name: "Cherries", taste: "Juicy"),
    Fruit(name: "Banana", taste: "Sweet"),
    Fruit(name: "Carambola", taste: "Tart"),
    Fruit(name: "Peer", taste: "Sweat"),
]

var listOfCountries:[Country] = [
    Country(name: "USA", listOfFruit: ["Apple", "Orange", "Cherries"]),
    Country(name: "Brazil", listOfFruit: ["Orange", "Banana", "Peer", "Carambola"]),
    Country(name: "Canada", listOfFruit: ["Cherries", "Peer", "Cherries", "Apple"]),
]

func getSortedFriutListForCountry(_ countryName: String) -> [Fruit] {
    let fruitNames = listOfCountries.first(where: { $0.name == countryName })?.listOfFruit
    return listOfFruits.filter { fruitNames?.contains($0.name) ?? false }.sorted { f1, f2 in
        f1.name < f2.name
    }
}
0 голосов
/ 03 июля 2019

Используйте compactMap(_:) для сопоставления каждого имени объекта String listOFFruitInCanada с Fruit в listOfFruits, используя first(where:), то есть

var listOfFilterAndSortedFruits = listOFFruitInCanada.compactMap({ (name) -> Fruit? in
    listOfFruits.first(where: { $0.name == name })
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...