【问题标题】:How to sort and filter of an array based on another array?如何根据另一个数组对数组进行排序和过滤?
【发布时间】:2019-07-03 04:53:17
【问题描述】:

如何根据不同的国家/地区对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]()

【问题讨论】:

  • 你能说清楚吗
  • 为什么不在listofCountries 中使用Fruit 数组而不是String 数组。
  • var listOfFruit: [String]更改为var listOfFruit: [Fruit]

标签: arrays swift sorting filter


【解决方案1】:

您正在使用一系列水果:

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 值类型。

【讨论】:

    【解决方案2】:

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

    var listOfFilterAndSortedFruits = listOFFruitInCanada.compactMap({ (name) -> Fruit? in
        listOfFruits.first(where: { $0.name == name })
    })
    

    【讨论】:

    • 这太棒了!非常感谢!
    • 太棒了。如果答案有效,请接受(在左侧打勾)。
    【解决方案3】:

    据我了解您的问题,您希望获得给定国家名称的水果排序列表,如果是这种情况,那么下面的代码将满足您的目的。

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

    【讨论】:

      猜你喜欢
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 2020-12-04
      • 2023-03-05
      相关资源
      最近更新 更多