如何通过键过滤 NSArray:值,即在 NSDictionary

Posted

技术标签:

【中文标题】如何通过键过滤 NSArray:值,即在 NSDictionary【英文标题】:How to filter a NSArray by Key:value, that is in a NSDictionary 【发布时间】:2018-02-14 08:33:18 【问题描述】:

我试图弄清楚如何通过值“名称”过滤掉 NSArrays 的字典

// Is an Array of a dictionary, by key : values

var teamFilteredList = [[String:Any]]()
var teamList = [[String:Any]]() 

获取:

    let string = "https://api/connect/"
    let url = NSURL(string: string)
    let request = NSMutableURLRequest(url: url! as URL)
    request.httpMethod = "GET"
    let session = URLSession.shared
    let tache = session.dataTask(with: request as URLRequest)  (data, response, error) -> Void in
        if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSArray 
            print(jsonObj)
            teamList = jsonObj as! [[String : Any]]

            DispatchQueue.main.async 
                self.teamCollectionView.reloadData()
            
        
    
    tache.resume()

此代码是结果并被放入 teamList

JSON:

(
    id = 1;
    logo = "testLogo";
    name = "testTeam1";
    "url" = "https://example.com";
,
    
    id = 2;
    logo = "testLogo";
    name = "testTeam2";
    "url" = "https://example.com";
,
    
    id = 3;
    logo = "testLogo";
    name = "testTeam3";
    "url" = "https://example.com";
)

放入 teamList 后的外观示例:

let example = [[id: "1", logo: "image", name: "testTeam1", url: "https"], [id: "2", logo: "image", name: "testTeam2", url: "https"]] 

试图过滤的代码:

 let array2Name = teamFilteredList.flatMap  $0["name"] 
    teamFilteredList = teamList.reduce(teamFilteredList,  result, value in
        !array2Name.contains(where:  $0 as! _OptionalNilComparisonType == value["testTeam3"] ) ? result + [value]: result
    )

到目前为止,这段代码很糟糕。但是网上没有其他东西可以告诉我如何做到这一点。所以我被卡住了。

导致崩溃:

无法转换“__NSCFString”类型的值

更新:

我有一个集合视图,它是由 NSURL 从获取中填充的,它给了我一个充满 NSArrays 的字典,我想通过一个已经在 NSArray 索引中的值过滤掉该字典中的所有 NSArray 索引键:“名称”

此链接最终答案中已回答的问题,但它不是最新的并且会产生错误。 here

【问题讨论】:

无法转换类型为 '__NSCFString 的值。您正在尝试将 String 存储到另一种数据类型。所以它越来越崩溃 好的,谢谢,必须有一个更简单的方法来做到这一点。 @McDonal_11 你想做什么? 我把它放在更新中@McDonal_11 鼓励您使用自定义类或结构而不是字典。它让事情变得简单。 【参考方案1】:

使用自定义结构和JSONDecoder 会容易得多

创建一个结构

struct Team : Decodable 
    let id : Int
    let logo : String
    let name : String
    let url : URL

创建数组

var teamList = [Team]()
var teamFilteredList = [Team]()

解码 JSON

let string = "https://api/connect/"
let url = URL(string: string)!
let task = URLSession.shared.dataTask(with: url)  (data, response, error) in
    if let error = error  print(error); return 
    do 
        self.teamList = try JSONDecoder().decode([Team].self, from: data!)
        DispatchQueue.main.async 
            self.teamCollectionView.reloadData()
        
     catch 
        print(error)
    

task.resume()

并过滤数组

teamFilteredList = teamList.filter $0.name == "testTeam3" 

【讨论】:

【参考方案2】:

尝试使用这个谓词

teamFilteredList.filter( fromDict in return !array2Name.contains(where:  $0 == fromDict["name"] as? String ?? ""))

诀窍在于 Swift 的错误没有表现力。它说don't use where,为什么?因为编译器真的需要一个字符串,因为你的闭包不正确。

如果array2Name 也是字典。尝试将where 子句更改为:

where:  ($0["name"] as? String ?? "<<Empty1>>") == (fromDict["name"] as? String ?? "<<Empty2>>") 

所以整个函数是:

teamFilteredList.filter( fromDict in return !array2Name.contains(where:  ($0["name"] as? String ?? "<<Empty1>>") == (fromDict["name"] as? String ?? "<<Empty2>>") ))

如果你想学习更有效的函数式编程并且不介意一些 javascript,试试这个

Learn Effective Functional Programming in JavaScript)

【讨论】:

比以往任何时候都更接近,大声笑虽然我收到错误'二进制运算符'=='不能应用于'[String:Any]'和'String'类型的操作数 array2Name 我用已经填充的变量 teamList 替换。我得到了错误 看来array2Name 不是字符串数组。这段代码是关于 array2Name 是一个字符串数组。所以试试这个where: ($0["name"] as? String ?? "&lt;&lt;Empty1&gt;&gt;" == fromDict["name" as? String ?? "&lt;&lt;Empty2&gt;&gt;"]) 这样做是为了使 > 和 > 都不是字符串时条件失败

以上是关于如何通过键过滤 NSArray:值,即在 NSDictionary的主要内容,如果未能解决你的问题,请参考以下文章

获取过滤值的字典键

从 NSArray 动态生成 NSPredicate

如何遍历对象字典及其键

NSPredicate 针对 NSArray 中的嵌套值

使用 NSPredicate 根据 NSDictionary 键过滤 NSArray

如何通过过滤匹配条件从 NSArray 创建范围?