在Swift中混合for-in和if-let

时间:2014-10-25 07:43:55

标签: swift

我可以在一个语句中合并for-in和if-let吗?

    for item in array {
        if let f = item as? NSDictionary {
            result.addObject(newFile(f))
        }
    }

array由JSON制作,因此我不知道每个项目是否为NSDictionary。我得检查一下。

我正在寻找这样的事情:

for item as? NSDictionary in array {
 // code
}

像Python或Ruby一样。

3 个答案:

答案 0 :(得分:3)

@nickfalk走在正确的轨道上,但我们可以做得更好。不幸的是,他的结果会返回[AnyObject],然后你就可以用({I}}调用newFile。但是没关系,我们可以很容易地完成剩下的工作。

你想要的是部分地图。也就是说,您希望将一个列表的一些(但可能不是全部)元素映射到另一个列表(从AnyObjectFile,如果可以的话)。因此必须有一些选择规则,以及一些映射规则。可选让我们结合这些。让我们调用执行该f的函数。然后它的类型是:

f: T->U?

因此,有一些神奇的功能可能会将T转换为U。我们想用它来映射。听起来很简单:

extension Array {
  func partialMap<U>(f: T->U?) -> [U] {
    var result = [U]()
    for x in self {
      if let u = f(x) {
        result.append(u)
      }
    }
    return result
  }
}

所以现在我们已经隐藏了所有令人讨厌的突变和var以及我们不必去看它的地方。我们有一个函数,它从&#34;某些东西&#34;中获取映射函数。到了&#34;也许别的东西&#34;并返回一个&#34;我们可以映射的东西列表。&#34;

现在一切都很好,不可改变,可重复使用:

let result = array.partialMap { ($0 as? NSDictionary).map(newFile) }

哇那里。中间的map是什么?好吧,as?会返回NSDictionary?。当map是可选项时,如果可选项为None,则返回None,否则它会将该函数应用于该值并将其包装在Some中。所以整个过程需要AnyObject并返回File?就像我们想要的那样。一partialMap我们得到了答案。

答案 1 :(得分:3)

我可能会选择类似的东西:

let result = array.filter() { $0 is NSDictionary }

如果你需要result成为NSDictionary数组,你可以直接投射它:

let result = array.filter() { $0 is NSDictionary } as [NSDictionary]

答案 2 :(得分:1)

如果您的目标是将NSArray缩减为仅包含NSDictionary过滤器的数组,那么这是一个非常强大的工具。创建适当的过滤功能:

func filterForNSDictionary(object: AnyObject) -> Bool{
    return object.isKindOfClass(NSDictionary)
}

然后简单地将数组和函数传递给filter函数

let result = filter(array, filterForNSDictionary) 

正如@RobNapier所指出的,上面的解决方案最终会得到类型为[AnyObject]的结果数组,这当然可以很容易地解决:

let result = filter(array, filterForNSDictionary) as [NSDictionary]

如果你强制数组的类型错误,这可能会被认为是有风险的。 as [NSString](例如,9很可能会在你面前爆炸......

Rob的解决方案当然是非常棒的聪明,而@MattGibson提供了完美的速记,同时让我在这个领域成为绝对的初学者。