简体   繁体   中英

Swift matching elements within nested array of structs

I'm a Swift newbie and I'm trying to get to grips with the following data structure. I have an array ( categories ) of category structs. Each category struct contains an array of business structs stored as a value on the property items . I'm not sure how to represent this kind of thing but hopefully this pseudo-code makes it a little bit clearer:

categories: [category]
   - category: Struct
        .categoryId: Int
        .items: [business]
            - business: Struct
               .busId: Int
            - business: Struct
               .busId: Int
   - category: Struct
        .categoryId: Int
        .items: [business]
            - business: Struct
               .busId: Int
            - business: Struct
               .busId: Int

Given a busId I'm trying to return a matching business Struct and the categoryId in which it is contained. I've tried using FlatMap and Map but I'm going round in circles trying to unwrap and filter this data structure.

Any pointers/advice about approaches to take would be great.

Given a Business struct defined like this

struct Business {
    let busID: Int
}

A Category like this

struct Category {
    let categoryID: Int
    let business: [Business]
}

And a list of Category

let categories = [
    Category(categoryID: 0, business: [Business(busID:0)]),
    Category(categoryID: 1, business: [Business(busID:1), Business(busID:2)])
]

We can extract the categoryID and the Business having a given Int

func search(businessID: Int, categories: [Category]) -> (categoryID: Int, business:Business)? {
    let res = categories.reduce([Int:Business]()) { (res, category) ->  [Int:Business] in
        guard res.isEmpty else { return res }
        var res = res
        if let business = (category.business.filter { $0.busID == businessID }).first {
            res[category.categoryID] = business
        }
        return res
    }

    guard let categoryID = res.keys.first, business = res[categoryID] else  { return nil }
    return (categoryID, business)
}

Example

在此输入图像描述

Update

This is a shorter version which does not use reduce

func search(businessID: Int, categories: [Category]) -> (categoryID: Int, business:Business)? {
    guard let
        category = (categories.filter { $0.business.contains { $0.busID == businessID } } ).first,
        business = (category.business.filter { $0.busID == businessID } ).first
    else { return nil }
    return (category.categoryID, business)
}

How's this?

categories.filter{category in //filter the categories as the final result
    category.items //get the Businesses in the category
            .map{$0.busId} //get the busIds of the Businesses
            .contains(desiredBusinessID) //keep iff the desired busId is present
}

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