用对象过滤嵌套数组

时间:2018-07-16 11:24:29

标签: arrays swift filter

我有一个类别数组。每个Category实例都具有offers属性。

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

class Offer {
    var type : String?
}

//global variable
var categories = [ categ1, categ2, ...]

如何按offer.type筛选类别?

我已经尝试过:

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

它可以工作,但是在调用函数之后,第二时间数组为空。可能是因为要约被重写了?

然后我尝试了此操作(产生了相同的错误结果):

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

3 个答案:

答案 0 :(得分:3)

您只需filter所有没有要约的类别就等于您的类型。您可以通过以下方式实现这一目标:

  1. 过滤所有类别,然后
  2. filter内检查当前报价是否包含myType

代码:

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

请注意,category.offers?.[...]是可选值,因此,如果左边为?? false,则false返回nil


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
}

还要注意,我正在使用compactMap。它使我可以过滤掉offers为空或为零的类别。

答案 1 :(得分:1)

您可以使用简单的for-loop(函数式编程)代替let data = categories.filter { ($0.offers?.contains(where: {$0.type == "yourtype"})) ?? false } 。 第一个过滤器类别,然后检查商品是否包含特定类型(使用等于条件)

<a class="navbar-brand js-scroll-trigger" href="#page-top">
    <img class="logo-navbar" src="img/logo-1-img-black.png">
</a>

答案 2 :(得分:0)

如果要使用多个过滤器,例如一个模型中的一个字段和嵌套数组中的第二个字段,请检查

 let searchText = "a"
 let filteredCategoryList = list.filter { category in
     let categoryFilter = category.title?.range(of: searchText, options: .caseInsensitive) != nil
     let offerFilter = category.offers?.contains(where: { $0.type?.range(of: searchText, options: .caseInsensitive) != nil
     })

     return categoryFilter || offerFilter ?? false
 }