如何基于另一个数组对数组进行排序和过滤?

时间:2019-07-03 04:53:17

标签: arrays swift sorting filter

如何根据其他国家/地区对listOfFruits进行过滤和排序,并将其存储到listOfFilterAndSortedFruits?

例如: 如果我将CanadalistOfFruit一起选择:["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 :(得分:0)

使用 {{使用 compactMap(_:) 将每个名称String listOFFruitInCanada映射到Fruit中的listOfFruits对象1}} ,即

first(where:)

答案 1 :(得分:0)

您正在使用一系列水果:

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: ...)遍历整个数组(因为必须针对我们要搜索的每个水果重新遍历该数组,因此复杂度为{{1 }})。相反,我使用的是字典O(n)(在其中我们可以立即找到所需的fruitDictionary[...]对象,复杂度为Fruit)。


不相关,但您可以考虑使用O(1)类型:

struct

如果确实需要,可以使用struct Fruit { let name: String let taste: String } struct Country { let name: String let listOfFruit: [String] } 引用类型,但是如今,我们倾向于使用class值类型。

答案 2 :(得分:0)

据我所知,您想获取给定国家名称的水果分类列表,如果是这种情况,那么下面的代码将为您服务。

如果存在具有该名称的国家/地区,

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
    }
}