【问题标题】:Swift filter nested array of objectsSwift过滤嵌套的对象数组
【发布时间】:2016-06-09 15:24:41
【问题描述】:

我有一个业务对象数组。每个 Business 对象都包含一个键值对数组,其中一个元素可以是 ContentBlocks 对象的嵌套数组。

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:...
]

我可以使用类似这样的方法过滤数组以返回与唯一 busId 匹配的特定企业:

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

此外,我想通过过滤唯一的 contentId 来返回特定的 contentBlock(如有必要,我还可以传递业务“所有者”的 busId)。我真的在努力前进,所以任何指向正确方向的指针都会很棒。

【问题讨论】:

    标签: swift


    【解决方案1】:

    这是我认为您所问问题的解决方案:

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

    输出一个[ContentBlock],其中包含与所有Business 对象中的过滤器匹配的所有ContentBlock 对象。

    1. 第一个 flatMap 将Businesses 列表变成[ContentBlock?]
    2. flatMap 将[ContentBlock?] 扁平化为[ContentBlock]
    3. [ContentBlock] 被过滤

    【讨论】:

    • 感谢您的出色回答。当我尝试它时,编译器会抱怨:Value of type '[ContentBlock]' has no member 'contentId' 在最后一行。知道我做错了什么吗?
    • 如果 contentID 是一个键,它会像$0["contentId"] 这样写来访问该键的值。编译器给你错误,因为它当前被像一个属性一样被访问,我认为它不是。
    • @NSGangster 谢谢 - 我试过了,但它再次抱怨,这次是 Cannot subscript a value of type '[ContentBlock]' with an index of type 'String' 所以我尝试不带引号 - 同样的错误......嗯!
    • 模拟这个需要我一段时间(我需要制作这些结构,而不是什么)。你能告诉我你在 map 之后得到的类型,然后你在 flatMap 之后得到的类型?
    【解决方案2】:

    当您在处理模型并想搜索类的嵌套自定义对象时。

    这是类示例。

    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
       }
    }
    

    让我们创建一个 Model1 的数组。

    var arrData = [Model1]()
    

    就我而言,我想在可用性数组中进行搜索。所以我把逻辑放在下面,它工作得很好。

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

    这个快速代码将只返回匹配2019/09/17的记录

    【讨论】:

      【解决方案3】:

      试试这个:

      // 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 }
      }
      

      【讨论】:

      • 谢谢。答案stackoverflow.com/a/37730229/131385 是我认为可能的(只需要contentId)。您的建议非常适合我在应用程序其他地方需要的类似但略有不同的数据结构 + 过滤器。
      猜你喜欢
      • 1970-01-01
      • 2020-03-11
      • 2020-03-08
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      • 2020-09-17
      相关资源
      最近更新 更多