Сортировка массива структур по элементам в другом массиве (Swift) - PullRequest
0 голосов
/ 06 ноября 2018

Хорошо, поэтому я хочу отсортировать массив на основе другого массива. Хорошо, так что это звучит довольно запутанно, поэтому позвольте мне объяснить.

Хорошо, давайте сделаем пример приложения о покупке продуктов. Итак, у меня есть такой массив:

var fruitsArray = [String:Int]()

Скажем, значения массива

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

Хорошо, во-первых, я сортирую этот массив по Int по убыванию, что дает нам

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

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

struct List {
    var name:String = ""
    var items:[String] = [""]

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

, а затем массив List ...

var shoppingLists = [List]()

наконец, давайте добавим некоторые элементы к 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])]

Хорошо, вот где это становится довольно сложно. Я хочу отсортировать shoppingLists, посмотрев массив items в shoppingLists и сравнив их с fruitsArray. Позвольте мне показать вам, что я хочу, чтобы был конечный продукт, а затем я объясню, почему.

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])]

Хорошо, так почему же в мире это сортируется так? Давайте рассмотрим это элемент за элементом. Итак, список 3 находится сверху, потому что он содержит 3 элемента из fruitsArray. Теперь вы можете сказать, что список 4 также содержит 3 элемента из fruitsArray, и да, это правда, но список 3 содержит элементы из fruitsArray, которые имеют более высокий рейтинг. Оба списка 3 и 4 содержат [apple, strawberry], но список 3 содержит banana, а список 4 содержит grape. Banana outranksks "grape, поэтому сначала создаем список 3. Итак, двигаясь дальше, список 1 следует за списком 4, потому что он содержит [apple, banana], что по« рангу »выше, чем [apple, grape] в списке 2.

Хорошо, я действительно надеюсь, что это не смущало. Если у вас есть какие-либо вопросы или мне нужно уточнить, пожалуйста, задавайте! Большое спасибо за чтение этого, и я надеюсь, что вы можете помочь мне.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Используйте функцию reduce для вычисления ранга каждого списка и метод sorted для сортировки массива.

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
}
0 голосов
/ 06 ноября 2018

Для решения этой проблемы я использовал систему баллов, которая рассчитывала бы баллы для каждого списка в корзине покупок следующим образом:

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

Тогда, если мы отсортируем точечные результаты, мы получим;

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

Но это не решение. Нам нужно учитывать количество фруктов в каждом списке, и поэтому мы умножаем точки на элементы, которые совпадают с 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

Теперь, если мы отсортируем это, мы получим правильный результат:

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

Вот код:

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)
...