Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group array of objects by date in swift?

Need to group according to date. Response coming is in sorted format. Need to apply a filter on date to group. Response coming from backend:

[
    {
    "date": "date1"
    }, 
    {
    "date": "date1"
    },
    {
    "date": "date1"
    },
    {
    "date": "date2"
    },
    {
    "date": "date2"
    },
    {
    "date": "date3"
    }
]

Required:

[
    [
        "date": "2017-05-30T12:40:39.000Z",
        "message": [
            {
                "date_time": 2017-05-30T12: 40: 39.000Z
            }
        ]
    ],
    [
        "date": "2017-05-31T05:43:17.000Z",
        "message": [
            {
                "date_time": 2017-05-31T05: 43: 17.000Z
            },
            {
                "date_time": 2017-05-31T05: 44: 15.000Z
            },
            {
                "date_time": 2017-05-31T05: 44: 38.000Z
            }
        ]
    ]
]

I have checked multiple answers but wasn't able to find a good solution.

like image 535
Sahil Jaidka Avatar asked May 29 '17 12:05

Sahil Jaidka


2 Answers

This is my solution to group by date(just day, month and year):

let groupDic = Dictionary(grouping: arr) { (pendingCamera) -> DateComponents in

    let date = Calendar.current.dateComponents([.day, .year, .month], from: (pendingCamera.date)!)

    return date
}
like image 180
ironRoei Avatar answered Jan 03 '23 22:01

ironRoei


You can use an array extension.

extension Array {
  func sliced(by dateComponents: Set<Calendar.Component>, for key: KeyPath<Element, Date>) -> [Date: [Element]] {
    let initial: [Date: [Element]] = [:]
    let groupedByDateComponents = reduce(into: initial) { acc, cur in
      let components = Calendar.current.dateComponents(dateComponents, from: cur[keyPath: key])
      let date = Calendar.current.date(from: components)!
      let existing = acc[date] ?? []
      acc[date] = existing + [cur]
    }

    return groupedByDateComponents
  }
}

You can use it on any model property using the Swift 5 KeyPath

let grouped = models.sliced(by: [.year, .month, .day], for: \.createdAt)
like image 37
Rick Pasveer Avatar answered Jan 03 '23 23:01

Rick Pasveer