在Swift中测试数组中是否存在对象的速记方法?

28

目前,我有一个像这样的对象数组:

var myArr = [
  MyObject(name: "Abc", description: "Lorem ipsum 1."),
  MyObject(name: "Def", description: "Lorem ipsum 2."),
  MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]

在执行以下操作之前,我正在测试一个对象是否存在:

let item = myArr.filter { $0.name == "Def" }.first
if item != nil {
  // Do something...
}

但我希望有更短的方法来做这件事,因为我经常需要这样做。我想做类似于这样的事情,但它是无效的:

if myArr.contains { $0.name == "Def" } {
  // Do something...
}

有没有我遗漏的速记语法或更好的方法来做到这一点?


这个问题与这个问题有什么不同?它们看起来非常相似。 - Antonio
我正在学习并探索Swift。似乎我必须用长方法来做每件事,例如remove、contains、find等等。我已经被Underscore.js宠坏了,希望Swift中也有类似的东西:http://underscorejs.org - TruMan1
1
我也被C#中内置的lambda表达式宠坏了 :( - TruMan1
1
但是你是否被宠坏了,以至于不愿意阅读文档或学习语言? - matt
发现了这个很棒的 Swift 库,它是 Underscore.js 的一个移植版本,可以完成许多类似的功能:http://www.dollarswift.org - TruMan1
显示剩余2条评论
2个回答

58

为什么不使用内置的contains()函数?它有两种味道

func contains<S : SequenceType, L : BooleanType>(seq: S, predicate: @noescape (S.Generator.Element) -> L) -> Bool
func contains<S : SequenceType where S.Generator.Element : Equatable>(seq: S, x: S.Generator.Element) -> Bool

并且第一个接受一个谓词作为参数。

if contains(myArr, { $0.name == "Def" }) {
    println("yes")
}

更新:从Swift 2开始,全局的contains()函数已被协议扩展方法所取代:

extension SequenceType where Generator.Element : Equatable {
    func contains(element: Self.Generator.Element) -> Bool
}

extension SequenceType {
    func contains(@noescape predicate: (Self.Generator.Element) -> Bool) -> Bool
}

并且第一个(基于谓词的)用法是:

if myArr.contains( { $0.name == "Def" }) {
    print("yes")
}

Swift 3:

if myArr.contains(where: { $0.name == "Def" }) {
    print("yes")
}

1
接下来要介绍的是:发现有一个带谓词的“包含”方法,但却没有相应的“查找”版本所带来的沮丧... - Airspeed Velocity
如果包含(myArr,{ $0.name ==“Def” }){ println(“是的”) } 如何从数组中获取当前对象 - LC 웃
@MartinR,我想从一个数组中删除对象...不使用索引..你能帮忙吗? - LC 웃
@MartinR 我成功地使用了过滤器方法...但这是一个好的方式吗? - LC 웃
@MartinR 对不起,我在条件语句中使用了可选数组。 - AbdulMomen عبدالمؤمن
显示剩余3条评论

2

我认为要实现所需的行为,你需要创建一个扩展类来扩展数组,类似于下面这样:

extension Array {
    func contains(test: (T) -> Bool, action: (T) -> Void) {
        let filtered = self.filter(test)
        if(filtered.is​Empty) {
            action(filtered)
        }
    }
}

抱歉,我手头没有Xcode,如果我有语法错误,请见谅。然而,如果你经常使用它,你可以这样写:

myArr.contains({ $0.name == "Def"}) {
   // Do something...
}

我会将其重命名,以避免在您的代码中产生混淆。

请纠正我,如果没有任何元素通过测试,self.filter(test)不会产生一个空数组,在这种情况下永远不会是nil,对吗? - Josh Paradroid
我可以更新答案,因为只需要检查数组的大小,尽管现在苹果已经包含了适合个人需求的功能。 - Nathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接