我正在尝试过滤其中包含数组和字典的数组。我想根据服务的类型进行过滤,然后在属性数组下将其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"
}
]
}
]
}
]
}
]
}
}
答案 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,则无需继续进行操作。)