【问题标题】:How to filter for a specific key's value in an array?如何过滤数组中特定键的值?
【发布时间】:2017-10-27 06:00:14
【问题描述】:

我们有一个返回数组的 json 值:

  "sentMoney": [
                {
                    "amount": 3840.83,
                    "currency": "MXN",
                    "isMajor": false
                },
                {
                    "amount": 200,
                    "currency": "USD",
                    "isMajor": true
                }
            ]

我想要做的是过滤它,以便我可以获得“金额”键的值。这是我目前所拥有的,但我收到“没有下标成员”错误消息:

 let filteredItem = self.postTransferSuccess?.sentMoney.filter{$0["sentMoney"]}[0]
                    self.emailMessage.amount = filteredItem

感谢任何帮助!

【问题讨论】:

  • 创建一个Transaction 类型,即类或结构。让它有 3 个属性,amountcurrencyisMajor。然后根据其amount 属性进行排序,否则你会有很长的转换线,类似于拉马尔的回答

标签: arrays swift filtering


【解决方案1】:

由于您的 sentMoney 是具有 array of dictionary 值的键,因此您应该这样做:

 let resultObj =  (dict["sentMoney"] as? [[String:Any]])?.filter({ ($0["amount"] as? Double) == someValue }).first // dict should be the name of your dictionary

请记住,您的数据应该如下所示,所以不要使用花括号:

var dict = ["sentMoney": [
   ["amount": 3840.83,"currency": "MXN", "isMajor": false],
   ["amount": 200.0,"currency": "USD","isMajor": true]
  ]
]

您的第二个选择是将您的字典转换为结构,这样会更容易迭代。

struct Item {
    let amount:Double
    let currency:String
    let isMajor:Bool


    init?(_ dict:[String:Any]?) { //<-- failable init will return a nil if there an empty key
    guard let _dict = dict,
    let amount = _dict["amount"] as? Double,
    let currency = _dict["currency"] as? String,
    let isMajor = _dict["isMajor"] as? Bool
        else { return nil }

    self.amount = amount
    self.currency = currency
    self.isMajor = isMajor
   }

}

现在,当您需要迭代时,您将执行以下操作: var someValue = 200.0

 if let arr = dict["sentMoney"] as? [[String:Any]] {
        let items = arr.flatMap({ Item($0)}) //<-- will remove any optional item from your list
        let singleItem = items.first { $0.amount == someValue } 
     // or arr.flatMap({ Item($0) }).filter({ $0.amount == someValue}).first
  }

(Side Node) 不惜一切代价避免使用!,使用 if let 或 guard 语句来解开你的选项。

【讨论】:

  • 这段代码非常不安全,因为它使用强制展开
  • 我有一个旁注:) @Gabox
  • filter({ $0.amount == someValue}).first 会不必要地迭代整个数组。您应该改用first(where:{ ... }) 方法
  • as! Double 更改为as? Double ?? 0as! String 更改为as? String ?? ""as! Bool 更改为as? Bool ?? falseas! [[String:Any]] 更改为as? [[String:Any]] ?? []
  • @LeoDabus 我急于提供该解决方案,但现在我进行了必要的更改:)
【解决方案2】:

我不完全确定您的问题是什么。 .filter 在这里不是正确的功能,尽管 bc .filter 用于删除数组/集合中不需要的元素。 (因此您使用条件进行过滤,并且仅当该条件评估为真时,它才会将该值复制到新集合中)。

您可能正在寻找的是.map

如:

let amountsOnlyArray = sentMoney.map({ $0["amount"] })

这会给你[3840.43, 200]

如果您出于某种原因只想要第一项并且想忽略我 THINK 你应该能够做到

let firstAmountOnly = sentMoney[0]["amount"]

请注意,amountsOnlyArray 实际上是 [Any] 类型,因此您必须在某处进行一些转换。

请注意,这假设您有某种 sentMoney:[String:Any] 集合,我假设您的初始代码过滤器 sentMoney

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 2010-12-08
    • 2019-11-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    相关资源
    最近更新 更多