过滤嵌套的数组和字典

时间:2019-02-12 05:07:03

标签: ios arrays swift filter realm

我正在尝试过滤其中包含数组和字典的数组。我想根据服务的类型进行过滤,然后在属性数组下将其isPrimaryMailbox为“是”。 这就是我所做的:-

let services = Manager.realm().objects(Service.self).filter("type = %@", "MAILBOX")

let serviceWithPrimaryEmail = services.filter({$0.attributes.first?.value == "Yes"})

但这显示的是isPrimaryMailbox值为No

的数据。

下面是json响应:-

{
  "data": {
    "cust": [
      {
        "customerId": "2040349110",
        "serv": [
          {
            "bill": "2010007656959",
            "services": [
              {
"type": "MOBILE",
                "status": "ACTIVE",
                "plan": {
                  "name": "Mobil"
                },
                "addOns": [
                  {
                    "status": "Active"
                  }
                ],
                "hardware": [
                  {
                    "type": "HANDSET"
                  }
                ]
              },
              {
                "type": "MOBILE",
                "plan": {
                  "name": "Mobile Service"
                },
                "addOns": [
                  {
                    "status": "Active"
                  }
                ],
                "hardware": [
                  {
                    "type": "HANDSET",
                  }
                ]
              },
              {
                "type": "MAILBOX",
                "plan": {
                  "name": "Service"
                },
                "attributes": [
                  {
                    "name": "mailboxSize",
                    "value": "1 GB"
                  },
                  {
                    "name": "isPrimaryMailbox",
                    "value": "Yes"
                  }
                ]
              },
              {
                "type": "MAILBOX",
                "status": "ACTIVE",
                "plan": {
                  "name": "Service"
                },
                "attributes": [
                  {
                    "name": "mailboxSize",
                    "value": "1 GB"
                  },
                  {
                    "name": "isPrimaryMailbox",
                    "value": "No"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

2 个答案:

答案 0 :(得分:0)

您可以尝试以下方法:

let serviceWithPrimaryEmail = services.filter({$0.attributes.[1].value == "Yes"})
// I used the index 1 because as I see in you JSON data, the isPrimaryMailBox is always in the second row.

此外,您的JSON格式错误。如果要使用关联的数组,那么为什么必须将键和值分隔为不同的键值对?

attributes可以简单地是:

"attributes":  {
  "mailboxSize":"1 GB",
  "isPrimaryMailbox":true
}

使用布尔值而不是字符串“ YES”或“ NO”

这样,当您进行过滤时,您只需说出

let serviceWithPrimaryEmail = services.filter({$0.attributes["isPrimaryMailbox"]})

或者,如果您真的更喜欢字符串“ YES”,那么:

let serviceWithPrimaryEmail = services.filter({$0.attributes["isPrimaryMailbox"] == "YES"})

答案 1 :(得分:0)

我不知道服务对象的类型。但是,这是从JSON获取主要电子邮件服务的方法:


typealias JSON = [String: Any]
let json = yourJSONDict as? JSON
let services = (((json["data"] as? JSON)?["cust"] as? JSON)?["serv"] as? JSON)?["services"] as? [JSON]
let primaryEmailService = services?.filter { service in
    if (service["type"] as? String) == "MAILBOX" {
        for attribute in service["attributes"] as? [[String: String]] ?? [] {
            if (attribute["name"] == "isPrimaryMailbox") && (attribute["value"] == "Yes") {
                return true
            }
        }
    }

    return false
}
    .first

已编辑:

如果不想使用for循环,则可以使用filter并只减少:


let primaryEmailService = services?
    .filter {
        let attributes = $0["attributes"] as? [[String: String]] ?? []

        return ($0["type"] as? String) == "MAILBOX"
            && attributes.reduce(false, { $0 || (($1["name"] == "isPrimaryMailbox") && ($1["value"] == "Yes")) })
}
    .first

请注意,两种方法的最坏情况下的复杂度是相等的。但是第一种方法的最佳情况复杂度更好,因为您不必在reduce函数中循环所有属性。而且Swift编译器目前还不够聪明,无法在第一个匹配项后停止减少循环(false || true始终为true。如果为true,则无需继续进行操作。)