Chace
Chace

Reputation: 561

Results of sorting an array are unexpected

I have a an array of objects that contains a date value. I have calculated the date differences and returned the number of days left. Now I am trying to sort it so it appends based on the object with least number of days left.

I have been able to use this function:

func sortList() {
    item.sort { (first: Item, second: Item) -> Bool in
        return first.days() < second.days()
    }
} 

Which gives me this:

this

However as you can see the date which is equal to 0 is appended at the bottom.

This is how I am calculating the days difference:

func daysDiff(startDate: Date, endDate: Date) -> Int {
    let calendar = Calendar.current

    let date1 = calendar.startOfDay(for: startDate)
    let date2 = calendar.startOfDay(for: endDate)

    let a = calendar.dateComponents([.day], from: date1, to: date2)
    return a.value(for: .day)!
}

And this is how I am formatting it:

func days() -> String {
    let formatter = DateFormatter()

    formatter.dateFormat = "MM dd, yyyy"
    let date = formatter.date(from: itemDate!)

    let date1 = Date()
    let date2 = date
    let days = daysDiff(startDate: date1, endDate: date2!)
    if days > 1 {
        return "\(days) days left"
    } else if days == 1 {
        return "a day left"
    } else if days == 0 {
        return "Due today!"
    } else if days < 0 {
        return "Late"
    } else {
        return "\(days)"
    }
}

I am not really sure why this issue is happening.

Upvotes: 1

Views: 59

Answers (1)

rmaddy
rmaddy

Reputation: 318804

Your sort is based on the text from your days() function so you are sorting the data alphabetically based on your text. You should sort based on an actual integer value, not a string.

You should have two methods on your class.

  1. days() which returns an Int instead of a String.
  2. daysLabel which returns a String based on the result of days.

Use days when sorting by number. Use daysLabel when displaying an Item instance somewhere.

func days() -> Int {
    let formatter = DateFormatter()

    formatter.dateFormat = "MM dd, yyyy"
    let date = formatter.date(from: itemDate!)

    let date1 = Date()
    let date2 = date
    let days = daysDiff(startDate: date1, endDate: date2!)

     return days
}

func daysLabel() -> String {
    let days = days()

    if days > 1 {
        return "\(days) days left"
    } else if days == 1 {
        return "a day left"
    } else if days == 0 {
        return "Due today!"
    } else if days < 0 {
        return "Late"
    } else {
        return "\(days)"
    }
}

Upvotes: 3

Related Questions