0

For data below, I want to sort selected indexes by value density (value/weight) descending. When equal, I want to sort among 'equals' by the weight, ascending.

let values = [40, 50, 60, 80, 100, 120, 20, 10]
let weights = [20, 80, 60, 160, 50, 120, 10, 5]

// Selection array
let arr2 = [ 0, 1, 1, 0, 1, 0, 0, 1]

// Get index from selection
var selectedIndexes = [Int]()
arr2.enumerated().forEach { (index, element) in
    if element == 1 {
        selectedIndexes.append(index)
    }
}

// without any sorting 
print(selectedIndexes) // [1, 2, 4, 7]

// sort descending by  value density
selectedIndexes.sort(by: { Double(values[$0])/Double(weights[$0]) > Double(values[$1])/Double(weights[$1]) } )

print(selectedIndexes) // [4, 7, 2, 1]

Items at index 4 and 7 both have value density of 2.0. How could I make sort by weights ascendant when value density is equal? So I will have [7, 4, 2, 1] in selectedIndexes array

Wismin
  • 1,135
  • 7
  • 21
  • You should make a struct or class to contain these values. Having parallel arrays like this is a real pain in the ass. – Alexander Jan 15 '17 at 07:12

1 Answers1

1

You're going to want to package this data up into a struct or class. After that, making such manipulations becomes really easy!

struct Thing { // TODO: Name me
    let value: Double
    let weight: Double
    let selected: Bool

    var valueDensity: Double {
        return value / weight
    }
}

extension Thing: Comparable {
    public static func <(lhs: Thing, rhs: Thing) -> Bool {
        if lhs.valueDensity != rhs.valueDensity { // first sort by valueDensity
            return lhs.valueDensity > rhs.valueDensity // descending
        }
        return lhs.weight < rhs.weight // break ties in valueDensity with weight
    }

    public static func ==(lhs: Thing, rhs: Thing) -> Bool {
        return lhs.value == rhs.value
            && lhs.weight == rhs.weight
            && lhs.selected == rhs.selected
    }
}

let things = [
    Thing(value: 40,    weight: 20,  selected: false),
    Thing(value: 50,    weight: 80,  selected: true ),
    Thing(value: 60,    weight: 60,  selected: true ),
    Thing(value: 80,    weight: 160, selected: false),
    Thing(value: 100,   weight: 50,  selected: true ),
    Thing(value: 120,   weight: 120, selected: false),
    Thing(value: 20,    weight: 10,  selected: false),
    Thing(value: 10,    weight: 5,   selected: true ),
]
print("All things:\r\n\(things)\r\n\r\n")

let selectedThings = things.enumerated().filter{ offset, element in
    return element.selected
}
print("Selected things:\r\n\(selectedThings)\r\n\r\n")

let sortedThings = selectedThings.sorted{ $0.element < $1.element }
print("Sorted things: \r\n\(sortedThings)\r\n\r\n")

let sortedThingIndices = sortedThings.map{ $0.offset }
print("Sorted Thing indicies: \r\n\(sortedThingIndices)\r\n\r\n")
Alexander
  • 59,041
  • 12
  • 98
  • 151