Как отфильтровать массив объектов по имени дублированных элементов по условиям в Swift - PullRequest
0 голосов
/ 18 октября 2019

У меня есть массив объектов с дублированным значением свойств объекта для некоторых объектов, и мне нужно отфильтровать его в соответствии с некоторыми условиями свойств объекта

У меня есть что-то похожее на следующий код:

Модель:

struct MyObject {
    var name: String
    var id: String
    var times: Int
    var value: Double
}

Массив:

Let objectArray = [
            MyObject(name: “Obj1”, id: “123”, times: 1, value: 3.0),
            MyObject(name: “Obj2”, id: “456”, times: 1, value: 2.3),
            MyObject(name: “Obj3”, id: “789”, times: 1, value: 1.0),
            MyObject(name: “Obj2”, id: “456”, times: 2, value: 3.3),
            MyObject(name: “Obj2”, id: “456”, times: 3, value: 4.7),
            MyObject(name: “Obj4”, id: “212”, times: 1, value: 2.4)
        ]

Я реализовал функцию расширения Array, чтобы удалить дублирующиеся элементы в массиве, но этого недостаточно в этом случае:

func filterDuplicate<T>(_ keyValue:(Element)->T) -> [Element] {
      var uniqueKeys = Set<String>()
      return filter{ uniqueKeys.insert("\(keyValue($0))").inserted }
   }

Мне нужно отфильтровать objectArray, чтобы получить массив без дублированных объектов с условием сохранения максимального значения свойства times, то есть конечный результат должен быть:

Ожидаемый результат:

filteredObjectArray =  [
            MyObject(name: “Obj1”, id: “123”, times: 1, value: 3.0),
            MyObject(name: “Obj3”, id: “789”, times: 1, value: 1.0),
            MyObject(name: “Obj2”, id: “456”, times: 3, value: 4.7),
            MyObject(name: “Obj4”, id: “212”, times: 1, value: 2.4)
        ]

С повторяющимся элементом Obj2, отфильтрованным по times property = 3

Ответы [ 2 ]

0 голосов
/ 18 октября 2019

Вы можете использовать уменьшение в этом случае:

    let resultArray = objectArray.reduce([]) { (nextResult, obj) -> [MyObject] in
        var tempArray = nextResult
        if let existObj = tempArray.first(where: { $0.name == obj.name && $0.id == obj.id }) {
            if obj.times > existObj.times {
                tempArray.removeAll(where: { $0.name == existObj.name })
                tempArray.append(obj)
            }
        } else {
            tempArray.append(obj)
        }
        return tempArray
    }
0 голосов
/ 18 октября 2019

Вот решение, использующее Reduce (into :) для фильтрации уникальных объектов

let uniqueAndHighest = objectArray.reduce(into: [MyObject]()) { array, object in
    if let index = array.firstIndex(where: { $0.id == object.id }) {
        if array[index].times < object.times {
            array[index] = object
        }
    } else {
        array.append(object)
    }
}

, и альтернативное решение с использованием словаря (группировка:)

let uniqueAndHighest = Dictionary(grouping: objectArray) {$0.id}
    .values
    .compactMap { $0.max {$0.times < $1.times}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...