Home > Software engineering >  Filter an Array of Structs by Months? SwiftUI
Filter an Array of Structs by Months? SwiftUI

Time:10-08

Hey guys I got something very similar going on in my project. But I was wondering when you have an array of structs, how would you be able to filter for items in specific month? Also the date is in epoch form.

import SwiftUI

struct TestStruct {
    var food: String
    var date: Double
    
}

class Test: ObservableObject{
    
    
    let food1 = TestStruct(food: "Hamburger", date: 1641058794)
    
    
    let food2 = TestStruct(food: "HotDog", date: 1651426794)
    
    
    let food3 = TestStruct(food: "icecream", date: 1652204394)
    
    
    let foodForYear: [TestStruct] = [food1, food2, food3]
    
}

CodePudding user response:

You can achieve that by using a simple filter on the array, and getting the TimeInterval you need in order to do the filter, here is a simple example:

       import Foundation


    struct TestStruct {
        var food: String
        var date: Double
        
        var parsedDate: Date {
            Date(timeIntervalSince1970: date)
        }
        
        var monthNumber: Int {
            Calendar.current.component(.month, from: parsedDate)
        }
    }

    class Test: ObservableObject{
        
        let food1 = TestStruct(food: "Hamburger", date: 1641058794)
        let food2 = TestStruct(food: "HotDog", date: 1651426794)
        let food3 = TestStruct(food: "icecream", date: 1652204394)
        
        let foodForYear: [TestStruct] = [food1, food2, food3]
        
        func filterMonthy() {
            let fiteredByMonths = foodForYear.filter({$0.monthNumber == 1}) // any logic you want to apply
            print(fiteredByMonths)
        }
    }

Take a look at the documentation: Date

CodePudding user response:

The issue is that you are using epoch form itself instead of native Date:

struct TestStruct {
  var food: String
  var date: Date

  init(food: String, date: Double) {
   self.food = food
   self.date = Date(timeIntervalSince1970: date)
  }
}

In this case you can easy get month or year in a string format:

extension TestStruct {
  var monthName: String {
     return date.formatted(
           Date.FormatStyle()
           .year(.defaultDigits) // remove if you don't need it
           .month(.abbreviated) // you can choose .wide if you want other format or read help for more information
     )
  }
}

Now let's check it:

let foodForYear: [TestStruct] = ...
print(foodForYear.sorted{ $0.monthName > $1.monthName}) // sorting
let nameOfMonth = "SomeMonthName" // depends from your format style 
print(foodForYear
    .compactMap{
         if $0.monthName.contains(nameOfMonth) {
             return $0
         } else { return nil }
    }
)
  • Related