使用对象过滤嵌套数组

Asi*_*ike 2 arrays filter swift

我有一系列类别。每个类别实例都有优惠属性。

class Category {
   var offers : [Offer]?
   var title : String?
   var id : Int?
}

class Offer {
    var type : String?
}

//global variable
var categories = [ categ1, categ2, ...]
Run Code Online (Sandbox Code Playgroud)

如何按 Offer.type 过滤类别?

我已经尝试过:

return categories.map { (category) -> Category in
    let offers = category.offers?.filter { $0.type == myType }
    category.offers = offers
    return category
}
Run Code Online (Sandbox Code Playgroud)

它有效,但第二次调用函数后数组变空。可能是因为报价被重写了?

然后我尝试了这个(产生了相同的错误结果):

var resultCategories = [Category]()

for category in categories {
    guard let offers = category.offers else { continue }

    var newOffers = [Offer]()

    for offer in offers {
        if offer.type == myType {
            newOffers.append(offer)
        }
    }

    category.offers = newOffers
    resultCategories.append(category)
}

return resultCategories
Run Code Online (Sandbox Code Playgroud)

pac*_*ion 5

您应该简单地将filter所有没有优惠的类别与您的类型相同。您可以通过以下方式实现这一目标:

  1. 过滤您的所有类别并
  2. 检查filter当前报价是否包含myType

代码:

let filtered = categories.filter { category in
    category.offers?.contains(where: { $0.type == myType }) ?? false
}
Run Code Online (Sandbox Code Playgroud)

请注意,这category.offers?.[...]是可选值,因此如果左侧部分为 ,则?? false返回结果。falsenil


UPD。

但我预计类别将仅包含类型=“A”的报价。也许我没有准确描述问题。

您可以通过创建新的Category.

let filtered = categories.compactMap { category -> Category? in
    guard let offers = category.offers?.filter({ $0.type == "A" }) else { return nil }
    let other = Category()
    other.offers = offers
    return other
}
Run Code Online (Sandbox Code Playgroud)

另请注意,我正在使用compactMap. 它允许我用空或 nil 来过滤类别offers