简体   繁体   English

按另一个数组中的元素对结构数组进行排序

[英]Sorting struct array by elements in another array

I'm wanting to sort an array based off of another array.我想根据另一个数组对数组进行排序。 That probably sounds pretty confusing so let me explain.这可能听起来很令人困惑,所以让我解释一下。

Here is an example of an app about grocery shopping.这是一个关于杂货店购物的应用程序示例。 I have an array like this:我有一个这样的数组:

var fruitsArray = [String:Int]()

Let's say that the values of the array are假设数组的值是

[apple:32, banana:45, grape:7, strawberry:23]

First off, I sort this array by the Int , descendingly, which gives us首先,我按Int对这个数组进行降序排序,这给了我们

[banana:45 apple:32, strawberry:23, grape:7]

Ok great.太好了。 But now I want an array of shopping lists and each element of that array contains an array of food.但现在我想要一个购物清单数组,该数组的每个元素都包含一个食物数组。 So let's make a Struct ...所以让我们做一个Struct ......

struct List {
    var name:String = ""
    var items:[String] = [""]
    
    init(name: String, items: [String) {
        self.name = name
        self.items = items
    }
}

and then an array of List ...然后是一个List数组...

var shoppingLists = [List]()

finally, let's add some elements to shoppingLists ...最后,让我们向shoppingLists添加一些元素...

[List(name: List 1, items: [banana, pizza, watermelon, apple]),
List(name: List 2, items: [cookie, water, grape, apple]),
List(name: List 3, items: [apple, strawberry, banana, cheese]),
List(name: List 4, items: [apple, strawberry, grape, watermelon])]

This is where it gets kind of difficult.这就是它变得有点困难的地方。 I want to sort shoppingLists by looking at the items array in shoppingLists and comparing them with fruitsArray .我想排序shoppingLists通过查看items在阵列shoppingLists并将其与比较fruitsArray Let me show you what I want the final product would be and then I'll explain why.让我告诉你我想要的最终产品是什么,然后我会解释原因。

sortedShoppingList = 
[List(name: List 3, items: [apple, strawberry, banana, cheese]),
List(name: List 4, items: [apple, strawberry, grape, watermelon]),
List(name: List 1, items: [banana, pizza, watermelon, apple]),
List(name: List 2, items: [cookie, water, grape, apple])]

Why is it sorted like this?为什么会这样排序? Let's take it element by element.让我们一个元素一个元素。 So List 3 is at the top because it contains 3 elements from fruitsArray .所以列表 3 位于顶部,因为它包含来自fruitsArray 3 个元素。 Now you might be saying list 4 also contains 3 elements from fruitsArray and yes that's true, but list 3 contains elements from fruitsArray that are higher in "ranking".现在您可能会说列表 4 还包含来自fruitsArray 3 个元素,是的,这是真的,但列表 3 包含来自fruitsArray “排名”更高的元素。 Both list 3 and 4 contain [apple, strawberry] but list 3 contains banana while list 4 contains grape .列表 3 和列表 4 都包含[apple, strawberry]但列表 3 包含banana而列表 4 包含grape Banana outranksks" grape therefore making list 3 first. So moving on, List 1 is after list 4 because it contains [apple, banana] which is higher in "rank" than the [apple, grape] in list 2. Banana等级高于“ grape因此排在第 3 位。所以继续,列表 1 排在列表 4 之后,因为它包含的[apple, banana]比列表 2 中的[apple, grape] “等级”更高。

To tackle the problem I used a point system that would calculate points for each list in the shopping cart like so;为了解决这个问题,我使用了一个积分系统,可以像这样计算购物车中每个列表的积分;

List 1, items: banana + pizza + watermelon + apple = 77   
List 2, items: cookie + water + grape + apple = 30    
List 3, items: apple + strawberry + banana + cheese = 100    
List 4, items: apple+ strawberry + grape + watermelon = 62

Then if we sort the point results we would get;然后,如果我们对点结果进行排序,我们将得到;

List 3, items: [apple + strawberry + banana] = 100   
List 1, items: [banana + apple] = 77   
List 4, items: [apple + strawberry + grape] = 62   
List 2, items: [grape + apple] = 30

But this is not the solution.但这不是解决方案。 We need to consider the number of fruits in each list and so we multiply point by items that match fruitArray like so;我们需要考虑每个列表中的水果数量,因此我们将点乘以与fruitArray 匹配的项目,如下所示;

List 3, items: [apple + strawberry + banana] = 100 * 3 = 300  
List 1, items: [banana + apple] = 77 * 2 = 154  
List 4, items: [apple + strawberry + grape] = 62  * 3 = 186  
List 2, items: [grape + apple] = 30 * 2 = 78

Now if we sort that we get the right result:现在,如果我们排序,我们会得到正确的结果:

List 3, point = 300   
List 4, point = 186  
List 1, point = 154  
List 2, point = 78

Here is the code:这是代码:

import UIKit

struct List {
    var id:Int = -1
    var items:[String] = [""]
    var point = 0

    init(id: Int, items: [String]) {
        self.id = id
        self.items = items
    }
}

var result = [List]()
var fruitsArray = ["banana":45, "apple":32, "strawberry":23, "grape":7]
var shoppingLists = [List(id: 1, items: ["banana", "pizza", "watermelon", "apple"]),
                     List(id: 2, items: ["cookie", "water", "grape", "apple"]),
                     List(id: 3, items: ["apple", "strawberry", "banana", "cheese"]),
                     List(id: 4, items: ["apple", "strawberry", "grape", "watermelon"])]


func calcPoints(lists: [List]){
    for list in lists{
        for item in list.items{
            let index = fruitsArray.index(forKey: item)
            if index != nil{
                shoppingLists[list.id - 1].point = shoppingLists[list.id - 1].point + fruitsArray[index!].value
            }
            else{
                shoppingLists[list.id - 1].items = shoppingLists[list.id - 1].items.filter { $0 != item }
            }
        }
        shoppingLists[list.id - 1].point = shoppingLists[list.id - 1].point * shoppingLists[list.id - 1].items.count
    }
}

calcPoints(lists: shoppingLists)
result = shoppingLists.sorted(by: { $0.point > $1.point })
print(result)

Use reduce function to calculate rank of each List and sorted method to sort an Array.使用reduce函数计算每个List 的排名,使用sorted方法对Array 进行排序。

let sorted = shoppingLists.sorted { list1, list2 in
    let a = list1.items.reduce(0) { sum, nextItem in
        return sum + (fruitsArray[nextItem] ?? 0)
    }
    let b = list2.items.reduce(0) { sum, nextItem in
        return sum + (fruitsArray[nextItem] ?? 0)
    }
    return a > b
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM