James
James

Reputation: 1302

Swift filter nested array of objects

I have an array of Business objects. Each Business object contains an array of key-value pairs, one element of which can be a nested array of ContentBlocks objects.

var masterArray = [
        Business(busName: "Dave's Cafe", busId: 1, website: "http://www.davescafe.com", latLong: (45.541, -45.609),
            actions: [["title": "About Us", "contentId": "123", "actionType": "content"],
                ["title": "Website", "url": "http://www.davescafe.com", "actionType": "web"]],
            contentBlocks:[
                ContentBlock(busName: "Dave's Cafe", busId: 1, contentId: "123", title: "Testola!", body: "Hello there!")
            ]),
        Business(busName:...
]

I can filter the array to return a specific Businesses matching a unique busId by using something like this:

let rtnArray = masterArray.filter{$0.busId == id}
    if rtnArray.count == 1{
        return rtnArray[0]
    } else {
        return // feedback that no matches were found
    }

Additionally, I'd like to return a specific contentBlock by filtering on the unique contentId (if necessary I can also pass the busId of the Business 'owner'). I'm really struggling to move forward so any pointers in the right direction would be great.

Upvotes: 6

Views: 7621

Answers (3)

Sandeep Maurya
Sandeep Maurya

Reputation: 2089

When you are dealing with model and want to search the nested custom object of class.

Here is class example.

public final class Model1  {
// MARK: Properties

public var firstname: String?
public var lastname: String?
public var email: String?
public var availabilities: [Availability]?
public var username: String?
}

public final class Availability {
var date: String
var day : String

init(date: String, day: String) {
    self.date = date
    self.day = day

    }
}
public final class AvailData {
var am: String?
var pm: String?

init(am: String?,pm: String?) {
    self.am = am
    self.pm = pm
   }
}

let make an array of Model1.

var arrData = [Model1]()

In my case, I want to search in availabilities array. So I put below logic and it work perfectly.

 let searchData = arrData.filter({ singleObj -> Bool in
     let result = singleObj.availabilities?.filter({ $0.date == "2019/09/17" })
     return result?.count > 0 ? true : false
 })

This swift code will return only those records which match 2019/09/17

Upvotes: 3

Alexander
Alexander

Reputation: 63399

Here's a solution to what I think you're asking:

 var contentBlocks = masterArray
                         .flatMap{$0.contentBlocks}
                         .flatMap{$0}
                         .filter{$0.contentId == "123"}

Outputs a [ContentBlock] containing all ContentBlock objects that match the filter from within all Business objects.

  1. The first flatMap makes the list of Businesses into an [ContentBlock?]
  2. The flatMap flattens the [ContentBlock?] into a [ContentBlock]
  3. The [ContentBlock] is filtered

Upvotes: 9

Code Different
Code Different

Reputation: 93191

Try this:

// The busId and contentId you want to find
let busId = 1
let contentId = "123"

let contentBlocks = masterArray.flatMap {
    $0.contentBlocks.filter { $0.busId == busId && $0.contentId == contentId }
}

Upvotes: 2

Related Questions