Say we have the following Object, Priority & Requirement objects:
enum Priority: CaseIterable {
case priorityA = "priority_a"
case priorityB = "priority_b"
case priorityC = "priority_c"
case priorityD = "priority_d"
case priorityE = "priority_e"
case priorityF = "priority_f"
case priorityG = "priority_g"
...
var weight: Int {
switch self {
...
}
}
}
struct Object {
let name: String
let priorities: [Priority: Int]
}
enum RequirementBaseValue {
case any
case minimum(Int)
case maximum(Int)
}
struct Requirement {
let priority: Priority
let baseValue: RequirementBaseValue
}
An example:
let requirementA = Requirement(priority: .priorityB, baseValue: .any)
let requirementB = Requirement(priority: .priorityC, baseValue: .minimum(100))
let requirements = [requirementA, requirementB]
let aPriorities = [..., .priorityB: 0, .priorityC: 0, ... ]
let objectA = Object(name: "object_a", priorities: aPriorities)
let bPriorities = [..., .priorityB: 950, .priorityC: 210, ... ]
let objectB = Object(name: "object_b", priorities: bPriorities)
let cPriorities = [..., .priorityB: 950, .priorityC: 300, ... ]
let objectC = Object(name: "object_c", priorities: cPriorities)
let dPriorities = [..., .priorityB: 250, .priorityC: 101, ... ]
let objectD = Object(name: "object_d", priorities: dPriorities)
let objects = [objectA, objectB, objectC, objectD]
The goal is to sort these objects:
let sortedObjects = objects.sorted(by: { ... })
For example, considering the weights of each priority is equal to 1, for the example above we would have:
print(sortedObjects)
// [objectC, objectB, objectD, objectA]
And a few details about how the sorting should be performed:
- If the requirement
baseValue
is set to any
: the higher the resultValue
the earlier it should appear in the sorted array.
- If the requirement value is either set to
minimum(Int)
or maximum(Int)
: if the priority doesn't match the condition, the object should be filtered out from the array, otherwise the higher the resultValue
the earlier it should appear in the sorted array.
- If an object's priorities dictionary doesn't contain a specific priority, we consider the
baseValue
for this priority to be equal to 0.
- The
resultValue
is obtained by multipying the weight property of a priority by the baseValue
of the priority.
- Each object will usually have between 80 to 200 priorities (maximum will be n=
Priority.allCases.count
).
- The objects array will usually have between 3000 to 5000 elements so performance will be important.
I was thinking of doing something like this:
let sortedObjects = objects.sorted(by: { object in
for requirement in requirements {
let baseValue = object.priorities[requirement.priority] ?? 0
let weight = requirement.priority.weight
let resultValue = baseValue * weight
...
}
return ...
}
But then I'm not sure how to return the boolean because there are multiple requirements & priorities for each object, and it's not just an AND or OR condition, but more of an else-if situation.
Thank you for your help!
question from:
https://stackoverflow.com/questions/65947568/sort-array-of-custom-objects-depending-on-dynamic-criterias