如何检查元素是否在数组中


475

在Swift中,如何检查数组中是否存在元素?Xcode没有针对contain,,include或的任何建议has,并且快速搜索本书不会发现任何建议。知道如何检查吗?我知道有一种方法find可以返回索引号,但是有没有一种方法可以返回布尔值,如ruby的#include?

我需要的示例:

var elements = [1,2,3,4,5]
if elements.contains(5) {
  //do something
}

11
if find(elements, 5) != nil { }还不够好吗?
马丁R

1
我希望有一种更清洁的东西,但是看起来不太好。我尚未在文档或书中找到任何东西。
jaredsmith 2014年

Answers:


860

斯威夫特2、3、4、5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
    print("yes")
}

contains()是一个协议扩展方法SequenceType(对于序列Equatable元素)而不是早期版本中的全局方法。

备注:

Swift的旧版本:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
    println("yes")
}

4
关于这种全局功能的任何文档吗?
里维拉2015年

3
如果数组中的每个项目(以及我们要搜索的项目)的类型为Dictionary <String,AnyObject>,这是否应该起作用?试图实现这一目标,但出现编译时错误。
ppalancica

7
@ppalancica:这要求数组元素符合Equatable协议(Dictionary<String, AnyObject>不是)。您可以使用它的第二个变体contains()作为谓词(比较stackoverflow.com/questions/29679486/…),例如if contains(array, { $0 == dict } ) ...
Martin R

如何从通用数组中搜索特定元素?说[AnyObject]?
Dhaval H. Nena

126

对于那些来这里寻找并从数组中删除对象的人:

斯威夫特1

if let index = find(itemList, item) {
    itemList.removeAtIndex(index)
}

迅捷2

if let index = itemList.indexOf(item) {
    itemList.removeAtIndex(index)
}

斯威夫特3,4,5

if let index = itemList.index(of: item) {
    itemList.remove(at: index)
}

3
请回答与该问题有关的内容。这个问题只是询问有关在数组中查找元素,而不是删除或更新它。您可以提出一个单独的问题,也可以自己回答。
Tejas

60

使用此扩展名:

extension Array {
    func contains<T where T : Equatable>(obj: T) -> Bool {
        return self.filter({$0 as? T == obj}).count > 0
    }
}

用于:

array.contains(1)

已针对Swift 2/3更新

请注意,从Swift 3(甚至2)开始,不再需要扩展,因为contains已将全局函数制成一对on的扩展方法Array,这使您可以执行以下任一操作:

let a = [ 1, 2, 3, 4 ]

a.contains(2)           // => true, only usable if Element : Equatable

a.contains { $0 < 1 }   // => false

10
查找更快。
Jim Balter 2014年

1
根据您的习惯,.contains可能会更直观和令人难忘
Pirijan 2014年

4
您能否通过分解来解释语法?我以前从未见过这种格式,而且您一次会发生很多高级操作!
侵略者2014年

40

如果要检查数组中是否包含自定义类或结构的实例,则需要实现Equatable协议,然后才能使用.contains(myObject)。

例如:

struct Cup: Equatable {
    let filled:Bool
}

static func ==(lhs:Cup, rhs:Cup) -> Bool { // Implement Equatable
    return lhs.filled == rhs.filled
}

那么您可以执行以下操作:

cupArray.contains(myCup)

提示:==覆盖应该在全局级别上,而不是在您的类/结构内


32

我用过滤器。

let results = elements.filter { el in el == 5 }
if results.count > 0 {
    // any matching items are in results
} else {
    // not found
}

如果需要,可以将其压缩为

if elements.filter({ el in el == 5 }).count > 0 {
}

希望能有所帮助。


Swift 2更新

欢呼使用默认实现!

if elements.contains(5) {
    // any matching items are in results
} else {
    // not found
}

我喜欢过滤器解决方案,因为您可以将其用于各种各样的事情。例如,我正在移植一些循环的代码,试图查看列表是否已经有一个项目,其中一个字段包含字符串值。这是Swift中的一行,在该字段上使用过滤器。
莫里·马科维兹

filter效率低下,因为它总是循环遍历所有元素,而不是在找到元素后立即返回。最好改用find()。
Thorsten

19

(快速3)

检查数组中是否存在元素(满足某些条件),如果存在,请继续使用第一个此类元素

如果目的是:

  1. 要检查数组中是否存在元素(/满足某些布尔条件,不一定要进行相等性测试),
  2. 如果是这样,请继续处理第一个此类元素,

然后一个替代contains(_:)作为blueprinted Sequencefirst(where:)Sequence

let elements = [1, 2, 3, 4, 5]

if let firstSuchElement = elements.first(where: { $0 == 4 }) {
    print(firstSuchElement) // 4
    // ...
}

在这个人为的示例中,它的用法似乎很愚蠢,但是如果查询非基本元素类型的数组是否存在满足某些条件的元素,则它非常有用。例如

struct Person {
    let age: Int
    let name: String
    init(_ age: Int, _ name: String) {
        self.age = age
        self.name = name
    }
}

let persons = [Person(17, "Fred"),   Person(16, "Susan"),
               Person(19, "Hannah"), Person(18, "Sarah"),
               Person(23, "Sam"),    Person(18, "Jane")]

if let eligableDriver = persons.first(where: { $0.age >= 18 }) {
    print("\(eligableDriver.name) can possibly drive the rental car in Sweden.")
    // ...
} // Hannah can possibly drive the rental car in Sweden.

let daniel = Person(18, "Daniel")
if let sameAgeAsDaniel = persons.first(where: { $0.age == daniel.age }) {
    print("\(sameAgeAsDaniel.name) is the same age as \(daniel.name).")
    // ...
} // Sarah is the same age as Daniel.

使用的任何链接操作.filter { ... some condition }.first都可以替换为first(where:)。后者显示出更好的意图,并且比的可能的非延迟设备具有性能优势.filter,因为它们在提取通过过滤器的(可能的)第一元素之前将通过整个阵列。


检查数组中是否存在元素(满足某些条件),如果存在,则删除第一个此类元素

以下评论查询:

如何firstSuchElement从阵列中删除?

与上述类似的用例是删除满足给定谓词的第一个元素。为此,该index(where:)方法Collection(可轻松用于数组集合)查找满足谓词的第一个元素的索引,此后可以将索引与to remove(at:)方法一起使用Array(可能;假定存在)删除该元素。

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let indexOfFirstSuchElement = elements.index(where: { $0 == "c" }) {
    elements.remove(at: indexOfFirstSuchElement)
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}

或者,如果您想从数组中删除该元素并使用,请对条件应用Optional:s map(_:)方法(对于.some(...)从中返回index(where:)),使用from的结果从index(where:)数组中删除并捕获已删除的元素(在可选的绑定子句中) 。

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let firstSuchElement = elements.index(where: { $0 == "c" })
    .map({ elements.remove(at: $0) }) {

    // if we enter here, the first such element have now been
    // remove from the array
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]

    // and we may work with it
    print(firstSuchElement) // c
}

请注意,在上面的人为设计示例中,数组成员是简单的值类型(String实例),因此使用谓词查找给定成员有点过分,因为我们可以使用@DogCoffee的答案index(of:)所示的更简单的方法来简单地测试相等性。但是,如果将上面的“查找与删除”方法应用于示例,则使用谓词是适当的(因为我们不再测试相等性而是满足提供的谓词)。Personindex(where:)


如何从数组中删除firstSuchElement?
i6x86

@ i6x86感谢您的问题。我以一个如何删除元素(以及如何删除和捕获已删除元素)的示例更新了我的答案。
dfri

14

最简单的方法是在数组上使用过滤器。

let result = elements.filter { $0==5 }

result如果找到的元素存在,则将具有它;如果该元素不存在,则将为空。因此,简单地检查是否result为空将告诉您元素是否存在于数组中。我将使用以下内容:

if result.isEmpty {
    // element does not exist in array
} else {
    // element exists
}

很好的解决方案。因此此方法返回一个数组。但是,我正在使用它来查找“ id”。在我的应用程序中,d是唯一的,因此只能有一个结果。有没有办法只返回1个结果?我现在正在使用result [0]
Dan Beaulieu

3
@DanBeaulieu做类似的事情let result = elements.filter { $0==5 }.first应该可以完成您想要的。
davetw12年

7

斯威夫特4/5

实现此目的的另一种方法是使用过滤器功能

var elements = [1,2,3,4,5]
if let object = elements.filter({ $0 == 5 }).first {
    print("found")
} else {
    print("not found")
}

6

从Swift 2.1开始,NSArrays containsObject可以像这样使用:

if myArray.containsObject(objectImCheckingFor){
    //myArray has the objectImCheckingFor
}

4
实际上,这是针对NSArray。不是快速的阵列
Tycho Pandelaar

是的,但是您可以将swift数组临时转换为NSArray:如果让tempNSArrayForChecking = mySwiftArray作为NSArray?其中tempNSArrayForChecking.containsObject(objectImCheckingFor){// myArray具有对象}
Vitalii,2016年

4

以防万一有人试图找到一个indexPath是否在选定的对象中(例如在UICollectionViewUITableView cellForItemAtIndexPath函数中):

    var isSelectedItem = false
    if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
        if contains(selectedIndexPaths, indexPath) {
            isSelectedItem = true
        }
    }

4

数组

let elements = [1, 2, 3, 4, 5, 5]

检查元素的存在

elements.contains(5) // true

获取元素索引

elements.firstIndex(of: 5) // 4
elements.firstIndex(of: 10) // nil

获取元素数

let results = elements.filter { element in element == 5 }
results.count // 2

3

这是我刚刚写的一个小扩展,用于检查我的委托数组是否包含委托对象(Swift 2)。:)它也适用于诸如魅力的值类型。

extension Array
{
    func containsObject(object: Any) -> Bool
    {
        if let anObject: AnyObject = object as? AnyObject
        {
            for obj in self
            {
                if let anObj: AnyObject = obj as? AnyObject
                {
                    if anObj === anObject { return true }
                }
            }
        }
        return false
    }
}

如果您有一个如何优化此代码的想法,那就让我知道。


2

如果用户找到特定的数组元素,则使用以下与整数值相同的代码。

var arrelemnts = ["sachin", "test", "test1", "test3"]

 if arrelemnts.contains("test"){
    print("found")   }else{
    print("not found")   }

2

迅速

如果您不使用对象,则可以使用此代码包含。

let elements = [ 10, 20, 30, 40, 50]

if elements.contains(50) {

   print("true")

}

如果您正在快速使用NSObject类。这个变量是根据我的要求。您可以根据需要进行修改。

var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!

这是相同的数据类型。

{ $0.user_id == cliectScreenSelectedObject.user_id }

如果要AnyObject类型。

{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }

完整状态

if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {

    cliectScreenSelected.append(cliectScreenSelectedObject)

    print("Object Added")

} else {

    print("Object already exists")

 }

1

像这样使用哈希表怎么办?

首先,创建“哈希图”通用函数,扩展Sequence协议。

extension Sequence where Element: Hashable {

    func hashMap() -> [Element: Int] {
        var dict: [Element: Int] = [:]
        for (i, value) in self.enumerated() {
            dict[value] = i
        }
        return dict
    }
}

只要数组中的项目符合Hashable(例如整数或字符串),此扩展名就可以使用,这是用法...

let numbers = Array(0...50) 
let hashMappedNumbers = numbers.hashMap()

let numToDetect = 35

let indexOfnumToDetect = hashMappedNumbers[numToDetect] // returns the index of the item and if all the elements in the array are different, it will work to get the index of the object!

print(indexOfnumToDetect) // prints 35

但是现在,让我们只关注元素是否在数组中。

let numExists = indexOfnumToDetect != nil // if the key does not exist 
means the number is not contained in the collection.

print(numExists) // prints true

0

Swift 4.2 +
您可以通过以下函数轻松地验证您的实例是否为数组。

func verifyIsObjectOfAnArray<T>(_ object: T) -> Bool {
   if let _ = object as? [T] {
      return true
   }

   return false
}

即使您可以按以下方式访问它。nil如果对象不是数组,您将收到。

func verifyIsObjectOfAnArray<T>(_ object: T) -> [T]? {
   if let array = object as? [T] {
      return array
   }

   return nil
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.