【问题标题】:Sort objects with multiple dynamic else-if statements使用多个动态 else-if 语句对对象进行排序
【发布时间】:2021-05-03 22:40:19
【问题描述】:

考虑到我们有以下几点:

typealias Fruit = String
typealias Count = Int

struct Smoothie {
   let uuid: String
   let fruits: [Fruit: Count]
}

let smoothies: [Smoothie] = ...

给定用户设置的条件数组:

let conditions: [Fruit] = ...

条件数组中最低的索引,我们认为最重要的是用于排序。

我想对冰沙数组进行排序,以便在 conditions 数组中包含最多水果 (Count) 的冰沙首先出现。

如果一个水果没有出现在 fruits 字典中,我们认为它的计数为 0。

例如:

let fruitsA = ["Apple": 3, "Mango": 4, "Pear": 8, "Cherry": 1, "Banana": 2]
let smoothieA = Smoothie(uuid: "smoothie_a", fruits: fruitsA)

let fruitsB = ["Apple": 10, "Mango": 9, "Grapes": 8, "Cherry": 9]
let smoothieB = Smoothie(uuid: "smoothie_b", fruits: fruitsB)

let fruitsC = ["Apple": 23, "Kiwi": 4, "Pear": 1, "Cherry": 17, "Banana": 8]
let smoothieC = Smoothie(uuid: "smoothie_c", fruits: fruitsC)

let fruitsD = ["Apple": 1, "Orange": 6, "Pear": 8]
let smoothieD = Smoothie(uuid: "smoothie_d", fruits: fruitsD)

let conditions: [Fruit] = ["Apple", "Banana", "Cherry"]

应该返回以下内容:

let sortedSmoothies = [smoothieC, smoothieB, smoothieA, smoothieD]

因为我们首先按 Apple 排序,然后按 Banana,然后按 Cherry 计数。

如果我知道它总是关于 Apple、Banana 和 Cherry,我可以执行以下操作并且它会起作用:

let sortedSmoothies = smoothies.sorted {
     if $0.fruits["Apple"] != $1.fruits["Apple"] {
         return $0.fruits["Apple"] > $1.fruits["Apple"]
     } else if $0.fruits["Banana"] != $1.fruits["Banana"] {
         return $0.fruits["Banana"] > $1.fruits["Banana"]
     } else {
         return $0.fruits["Cherry"] > $1.fruits["Cherry"]
     }
}

但在我的情况下,我不知道用户将在条件数组中选择哪些水果(以及其中多少个)进行过滤。

有人知道如何sort 这个吗?

谢谢!

【问题讨论】:

    标签: arrays swift sorting dictionary if-statement


    【解决方案1】:
    let sorted = [smoothieA, smoothieB, smoothieC, smoothieD].sorted { (a, b) in
        for condition in conditions {
            let aAmount = a.fruits[condition] ?? 0
            let bAmount = b.fruits[condition] ?? 0
            if aAmount == bAmount {
                continue
            }
            return aAmount > bAmount
        }
        return true
    }
    

    请记住,对于您的示例数据,由于“Apple”没有任何具有相同值的冰沙,因此任何测试都将返回相同的顺序。但是,您可以使用一些更有趣的数字进行测试,这些数字具有相同数量的水果的冰沙:

    let fruitsA = ["Apple": 10, "Mango": 4, "Pear": 8, "Cherry": 20, "Banana": 2]
    let smoothieA = Smoothie(uuid: "smoothie_a", fruits: fruitsA)
    
    let fruitsB = ["Apple": 10, "Mango": 9, "Grapes": 8, "Cherry": 9, "Banana": 2]
    let smoothieB = Smoothie(uuid: "smoothie_b", fruits: fruitsB)
    
    let fruitsC = ["Apple": 23, "Kiwi": 4, "Pear": 1, "Cherry": 17, "Banana": 8]
    let smoothieC = Smoothie(uuid: "smoothie_c", fruits: fruitsC)
    
    let fruitsD = ["Apple": 1, "Orange": 6, "Pear": 8]
    let smoothieD = Smoothie(uuid: "smoothie_d", fruits: fruitsD)
    

    【讨论】:

    • 您应该提取排序函数并为其编写测试用例。当前不正确,应用于两个相等的实例时会返回true。
    • 我一定遗漏了一些东西,但在这种情况下,我们期望看到两个相等的实例?
    • 您好,非常感谢您的回答,非常有帮助。当 Apple 有两个实例时,它应该比较条件数组的第二个元素,所以在我的示例中是 Banana。如果 Banana 的两个实例相等,那么它应该使用 Cherry 排序,然后因为条件数组中没有更多元素,它可以返回 false 而不进行排序。您有什么想法可以使它与您的示例一起使用吗?
    • 据我所知,这就是我的工作。
    • 在我的例子中(我的输入),C 是第一个,因为它有 23 个苹果。然后,A 和 C 的香蕉数量相同,因此比较樱桃,A 获胜。因此,结果是 C、A、B、D。将 B 上的香蕉数量更改为 3,顺序更改为 C、B、A、D。据我所知,这就是您所描述的。
    【解决方案2】:

    您可以创建一个水果数组的数组 - String[][],您可以将其称为 FruitsArr。您还可以创建一个水果数组或列表,该数组或列表可以容纳用户放入的水果数量。

    这都是松散的术语,因为 swift 语法是不熟悉的。看到太多 Java 语法可能会让您感到困惑,抱歉。不过,逻辑是通用的。

    for (int i = 0; i < fruits.length; i++){ 
    /*fruits is our imaginary array of user-input fruits. This is sorting the arrays one by one by each fruit in fruits*/
    String[] mostFruit; //fill it with zeroes or something.
        for (int j = 0; j < FruitsArr.length; j++){
            String[] thisFruit = FruitsArr[j]l
            if (thisFruit[i] > mostFruit[i]){mostFruit = thisFruit;}
         }
    }
    

    这会检查问题:thisFruit 中索引 i 的值是否大于 mostFruit 中索引 i 中的值?如果是这样,mostFruit 将变为 thisFruit。第一个至少有 1 个水果的 thisFruit 变为 mostFruit,因为 1 > 0。然后比较变得更加简单。

    您的循环将继续遍历水果 1、水果 2、水果 3,以及用户放入的其余部分。它将根据每个数组检查每个水果:

    水果 1:

    这个Fruit 有超过0 个fruit1 吗?

    (下一个)

    thisFruit 是否比当前 mostFruit 含有更多这种水果?

    (下一个)

    thisFruit 是否比当前 mostFruit 含有更多这种水果?

    因此它继续通过其余的水果数组和其余的水果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 2019-05-13
      相关资源
      最近更新 更多