-2

I have an array, SetDataList, which is populated with the information below:

["2019-04-30   Set 1:   8 Reps   55kg", "2019-05-02   Set 1:   5 Reps   70kg", "2019-05-02   Set 2:   4 Reps   70kg", "2019-05-02   Set 3:   2 Reps   75kg"]

I am currently using the below code to order the array so that the sets, 1, 2 and 3 are grouped and appear as is in the array above.

SetDataList.sort(by: {$0 < $1})

However, I would also like to order the array in date descending order. I have previously performed this by using the following code although, this approach scrambles the set order.

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"

let ordered = SetDataList.sorted { string1, string2 in
    guard let date1 = dateFormatter.date(from: string1), let date2 = dateFormatter.date(from: string2) else { return false }
    return date1 < date2
}

How can I implement multiple sorts? Thanks

ielyamani
  • 17,807
  • 10
  • 55
  • 90
gcpreston
  • 135
  • 1
  • 12
  • 2
    First parse the strings into an array of *objects,* then use [Sort array of objects with multiple criteria](https://stackoverflow.com/questions/37603960/swift-sort-array-of-objects-with-multiple-criteria) – Martin R May 03 '19 at 11:40
  • 1
    Consider that the `guard` expression fails and returns always `false`. The date formatter is irrelevant. The array is sorted by the leading date string representation. – vadian May 03 '19 at 11:43
  • Given your previous questions it looks like this string array is your own creation so rather than using it to start with I think you should concentrate on working with objects instead as suggested by @MartinR and you would avoid problems like this alltogether. – Joakim Danielson May 03 '19 at 12:05

1 Answers1

0

I would recommend using structs instead of strings, for example :

struct SetData {
    let setNumber: Int
    let date: Date
    let reps: Int
    let weight: Int
}

Let's start with this array :

let setDataList = ["2019-04-30   Set 1:   8 Reps   55kg",
                   "2019-05-02   Set 10:   20 Reps   70kg",
                   "2019-05-02   Set 1:   5 Reps   70kg",
                   "2019-05-02   Set 2:   4 Reps   70kg",
                   "2019-05-02   Set 3:   2 Reps   75kg"].shuffled()

Supposing the strings in the array all have the same format, you could sort setDataList this way :

let sorted = setDataList.sorted { string1, string2 in
    let dateDelimiter = string1.index(string1.startIndex, offsetBy: 9)
    let earlierDate =  string1[...dateDelimiter] < string2[...dateDelimiter]

    if earlierDate { return true }

    let firstSetStart = string1.index(string1.startIndex, offsetBy: 17)
    var firstSetEnd = firstSetStart

    while firstSetEnd < string1.endIndex,
        string1[firstSetEnd] != ":" {
        firstSetEnd = string1.index(after: firstSetEnd)
    }

    let secondSetStart = string2.index(string2.startIndex, offsetBy: 17)
    var secondSetEnd = secondSetStart

    while secondSetEnd < string2.endIndex,
        string2[secondSetEnd] != ":" {
            secondSetEnd = string2.index(after: secondSetEnd)
    }

    let sub1 = string1[firstSetStart..<firstSetEnd]
    let sub2 = string2[secondSetStart..<secondSetEnd]

    guard let setNbr1 = Int(sub1), let setNbr2 = Int(sub2) else {
        fatalError("Wrong string structure")
    }

    return setNbr1 < setNbr2
}

And you could check the result this way :

for element in sorted {
    print(element)
}

Which prints :

2019-04-30   Set 1:   8 Reps   55kg
2019-05-02   Set 1:   5 Reps   70kg
2019-05-02   Set 2:   4 Reps   70kg
2019-05-02   Set 3:   2 Reps   75kg
2019-05-02   Set 10:   20 Reps   70kg
ielyamani
  • 17,807
  • 10
  • 55
  • 90