I
I
Ilya2019-06-26 17:28:25
Swift
Ilya, 2019-06-26 17:28:25

How to make a structure filter?

Hello.
I receive here such array of the data.

array
[
  {
"idSite": 204233,
"status": 0,
"Name": "",
"timeOfStatus": null
},
  {
"idSite": 204234,
"status": 0,
"Name": "",
"timeOfStatus": null
},
  {
"idSite": 204235,
"status": 0,
"Name": "",
"timeOfStatus": null
},
  {
"idSite": 204236,
"status": 1,
"Name": "OK",
"timeOfStatus": "2019-06-26 12:58:16"
}
]

I store it in a struct:
self.Obj = try JSONDecoder().decode([StatusObjects].self, from: data)

The structure looks like this:
Structure
struct  StatusObjects: Decodable {
    let idSite: Int?
    let status: Int?
    let Name: String?
    let timeOfStatus: String?
    
    func convertToDictionary() -> Any {
        return ["idSite": idSite!, "status": status!, "Name": Name!,"timeOfStatus": timeOfStatus!]
        
    }
}

How do I filter a struct or array . So that only objects with:
"status": 1

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
doublench21, 2019-06-26
@ynizhenie

I'll show you two options.
-------------------------------------------------- ------
A simple variant (aka Dummi):
Normal filtering, after the memory has already been allocated. Simple, but memory spread and speed are lower.
-------------------------------------------------- ------ Advanced
variant : Correcting the name of the properties. Let's convert the dates to the appropriate format. We carry out our custom encoding, tracking the status and throwing out an error so as not to allocate memory in vain.

Illuminated code
2QkNeGLn.png
Text code
import Foundation

    let json = """
    [{
        "idSite": 204233,
        "status": 0,
        "Name": "",
        "timeOfStatus": null
    },
    {
        "idSite": 204234,
        "status": 0,
        "Name": "",
        "timeOfStatus": null
    },
    {
        "idSite": 204235,
        "status": 0,
        "Name": "",
        "timeOfStatus": null
    },
    {
        "idSite": 204236,
        "status": 1,
        "Name": "OK",
        "timeOfStatus": "2019-06-26 12:58:16"
    }]
    """

    struct SomeStruct: Decodable {
      let idSite: Int
      let status: Bool
      let name: String
      let timeOfStatus: Date?

      // Преобразуем Name -> name
      private enum CodingKeys: String, CodingKey {
        case idSite
        case status
        case name = "Name"
        case timeOfStatus
      }

      init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.idSite = try container.decode(Int.self, forKey: .idSite)

        // Выбрасываем ошибку, если статус не равен 1. Не выделяем зря память.
        let status = try container.decode(Int.self, forKey: .status)
        if status == 1 {
          self.status = true
        } else {
          throw DecodingError.dataCorruptedError(forKey: .status, in: container, debugDescription: "Status mast be `1`")
        }

        self.name = try container.decode(String.self, forKey: .name)

        // Преобразуем строку с датой в объект для работы с датами Date
        let date = try? container.decode(String.self, forKey: .timeOfStatus)
        let dateFormatter: DateFormatter = {
          $0.dateFormat = "yyyy-MM-dd HH:mm:ss"
          $0.calendar = Calendar(identifier: .iso8601)
          $0.timeZone = TimeZone(secondsFromGMT: 0)
          $0.locale = Locale(identifier: "en_US_POSIX")
          return $0
        }(DateFormatter())
        self.timeOfStatus = date != nil ? dateFormatter.date(from: date!) : nil
      }
    }

    // Тип обёртка, которая даст легко отфильтровать данные, от тех, которые не прошли из-за статуса.
    enum Throwable<T: Decodable>: Decodable {
      case success(T), failure(Error)

      init(from decoder: Decoder) throws {
        do {
          let decoded = try T(from: decoder)
          self = .success(decoded)
        } catch let error {
          self = .failure(error)
        }
      }

      var value: T? {
        switch self {
        case .failure(_):
          return nil
        case .success(let value):
          return value
        }
      }
    }


    let decoder = JSONDecoder()
    let arrayOfSomeStructs = try! decoder.decode([Throwable<SomeStruct>].self, from: json.data(using: .utf8)!)
    let filteredArrayOfSomeStructs = arrayOfSomeStructs.compactMap{ $0.value }
    print(filteredArrayOfSomeStructs.count)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question