Swift:过滤字典

war*_*rly 51 ios swift

我想在swift中过滤字典:

var data: [String: String] = [:]
data = data.filter { $0.1 == "Test" }
Run Code Online (Sandbox Code Playgroud)

上面的过滤器代码在swift 2下编译但产生以下错误:

无法将类型'[(String,String)]'的值赋给类型'[String:String]'的值

这是swift编译器中的一个错误,还是这不是在swift中过滤字典的正确方法?

非常感谢你提前!

aya*_*aio 90

这已在Swift 4中修复

let data = ["a": 0, "b": 42]
let filtered = data.filter { $0.value > 10 }
print(filtered) // ["b": 42]
Run Code Online (Sandbox Code Playgroud)

在Swift 4中,过滤的字典返回字典.


Swift 2和3的原始答案

问题是这data是一个字典,但结果filter是一个数组,所以错误信息表明你不能将后者的结果分配给前者.

您可以为结果数组创建一个新的变量/常量:

let data: [String: String] = [:]
let filtered = data.filter { $0.1 == "Test" }
Run Code Online (Sandbox Code Playgroud)

filtered是一组元组:[(String, String)].

过滤后,如果您需要,可以重新创建新词典:

var newData = [String:String]()
for result in filtered {
    newData[result.0] = result.1
}
Run Code Online (Sandbox Code Playgroud)

如果您决定不使用,filter您可以改变原始字典或其副本:

var data = ["a":"Test", "b":"nope"]
for (key, value) in data {
    if value != "Test" {
        data.removeValueForKey(key)
    }
}
print(data) // ["a": "Test"]
Run Code Online (Sandbox Code Playgroud)

注意:在Swift 3中,removeValueForKey已经重命名removeValue(forKey:),所以在这个例子中它变成了data.removeValue(forKey: key).

  • 好的,谢谢你:)在我看来,这只是苹果的愚蠢.当我过滤字典时,我期待一个字典作为回报...我将我的代码更改为一个数组,并使用组合结构来包含键和值(这样我不会被迫使用字符串键)而不是我使用再次使用过滤器功能,因为这是最简洁的方法. (20认同)
  • 任何人都知道为什么Dictionary.filter不会返回字典?我很好奇. (4认同)

Een*_*dje 15

data.forEach { if $1 != "Test" { data[$0] = nil } }
Run Code Online (Sandbox Code Playgroud)

只是另一种方法(稍微简化)来过滤掉字典中的对象.


use*_*341 7

根据Apple文档,过滤:

返回一个数组,该数组按顺序包含满足给定谓词的序列元素.

https://developer.apple.com/reference/swift/sequence/1641239-filter

我发现自己需要做OP所要求的事情并最终编写以下扩展(Swift 3):

extension Dictionary
{
  func filteredDictionary(_ isIncluded: (Key, Value) -> Bool)  -> Dictionary<Key, Value>
  {
    return self.filter(isIncluded).toDictionary(byTransforming: { $0 })
  }
}

extension Array
{
  func toDictionary<H:Hashable, T>(byTransforming transformer: (Element) -> (H, T)) -> Dictionary<H, T>
  {
    var result = Dictionary<H,T>()
    self.forEach({ element in
      let (key,value) = transformer(element)
      result[key] = value
    })
    return result
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let data = ["a":"yes", "b":"nope", "c":"oui", "d":"nyet"]
let filtered = data.filteredDictionary({ $0.1 >= "o" })

// filtered will be a dictionary containing ["a": "yes", "c": "oui"]
Run Code Online (Sandbox Code Playgroud)