简体   繁体   中英

Nested Array filter swift

I'm trying to filter the data from the sub_category array and show on the data in which isSelected is true. I have tried using flatmap and filter but am still not able to achieve the desired output. Please help.

{
  "data": [
    {
      "category_name": "Social Sites",
      "sub_category": [
        {
          "sub_category_name": "Instagram",
          "isSelected" : true
        },
        {
          "sub_category_name": "Facebook",
          "isSelected" : true
        },
        {
          "sub_category_name": "Twitter",
          "isSelected" : false
        }
      ]
    },
    {
      "category_name": "",
      "sub_category": [
        {
          "sub_category_name": "State",
          "isSelected" : false
        }
      ]
    },
    {
      "category_name": "Sports",
      "sub_category": [
        {
          "sub_category_name": "Cricket",
          "isSelected" : true
        },
        {
          "sub_category_name": "Hockey",
          "isSelected" : false
        }
      ]
    }
  ]
}

Desired Output is only for isSelected = true

{
  "data": [
    {
      "category_name": "Social Sites",
      "sub_category": [
        {
          "sub_category_name": "Instagram",
          "isSelected" : true
        },
        {
          "sub_category_name": "Facebook",
          "isSelected" : true
        }
      ]
    },
    {
      "category_name": "Sports",
      "sub_category": [
        {
          "sub_category_name": "Cricket",
          "isSelected" : true
        }
      ]
    }
  ]
}

I have tried using flatMap and filter, the following is my code.(But not able to achieve the desired output.)

let filtered = self.itemModelArray.flatMap { item in
            item.subCategory!.filter({ (subCat) -> Bool in
                subCat.isSelected == true
            })
        }

The above code gives me the array of subCategory,that is not what I want.

The following is my model

// MARK: - Item
struct Item: Codable {
    let category_name: String
    var sub_category: [SubCategory]
    
        init(cat:String,subCat:[SubCategory]){
            self.category_name = cat
            self.sub_category = subCat
        }
}

// MARK: - SubCategory
struct SubCategory: Codable {
    let sub_category_name: String
    var isSelected : Bool = false
    init(subCat:String){
        self.sub_category_name = subCat
    }

Something like this would filter out both empty categories & non-selected sub-categories:

import Foundation

let json: String = <the json in the question, omited for brevity> 

struct Model: Codable {
    let data: [Category]
    
    struct Category: Codable {
        let category_name: String 
        let sub_category: [SubCategory]
    }
    
    struct SubCategory: Codable {
        let sub_category_name: String 
        let isSelected: Bool
    }
}

// Note: Handle any errors properly in production code
let model = try? JSONDecoder().decode(Model.self, from: Data(json.utf8))

var output: [Model.Category] = []

for category in model?.data ?? [] {
    let selectedSubCategories = category.sub_category.filter(\.isSelected)
    if !selectedSubCategories.isEmpty {
        output.append(Model.Category(category_name: category.category_name, sub_category: selectedSubCategories))
    }
}

which produces an array of 2 categories:

dump(output)

▿ 2 elements
  ▿ main.Model.Category
    - category_name: "Social Sites"
    ▿ sub_category: 2 elements
      ▿ main.Model.SubCategory
        - sub_category_name: "Instagram"
        - isSelected: true
      ▿ main.Model.SubCategory
        - sub_category_name: "Facebook"
        - isSelected: true
  ▿ main.Model.Category
    - category_name: "Sports"
    ▿ sub_category: 1 element
      ▿ main.Model.SubCategory
        - sub_category_name: "Cricket"
        - isSelected: true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM