【问题标题】:How to check if an element is in an array如何检查一个元素是否在数组中
【发布时间】:2014-07-28 21:58:50
【问题描述】:

在 Swift 中,如何检查一个元素是否存在于数组中? Xcode 没有任何关于containincludehas 的建议,快速搜索这本书一无所获。知道如何检查吗?我知道有一种方法find 可以返回索引号,但是有没有一种方法可以返回像ruby 的#include? 这样的布尔值?

我需要的示例:

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

【问题讨论】:

  • if find(elements, 5) != nil { } 不够好?
  • 我希望有更干净的东西,但看起来不太好。我还没有在文档或书中找到任何内容。

标签: arrays swift


【解决方案1】:

斯威夫特 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")
}

【讨论】:

  • 有关于这种全局函数的文档吗?
  • 如果数组中的每个项目(以及我们正在搜索的项目)都是 Dictionary 类型,这是否应该工作?试图实现这一点,但我得到编译时错误。
  • @ppalancica:这要求数组元素符合Equatable 协议(Dictionary<String, AnyObject> 不符合)。 contains() 的第二个变体采用谓词(比较 stackoverflow.com/questions/29679486/…)也许你可以使用它,例如if contains(array, { $0 == dict } ) ...
  • 如何从泛型数组中搜索特定元素?说[AnyObject]?
【解决方案2】:

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

斯威夫特 1

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

斯威夫特 2

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

斯威夫特 3、4

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

Swift 5.2

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

【讨论】:

    【解决方案3】:

    为 Swift 2+ 更新

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

    let a = [ 1, 2, 3, 4 ]
    
    a.contains(2)           // => true, only usable if Element : Equatable
    
    a.contains { $0 < 1 }   // => false
    

    Swift 1 的历史答案:

    使用这个扩展:(更新到 Swift 5.2

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

    用作:

    array.contains(1)
    

    【讨论】:

    • 不过,根据您的习惯,.contains 可能会感觉更直观和令人难忘
    • 你能分解一下你的语法吗?我以前从未见过这种格式,而且你同时发生了很多高级的事情!
    • 我将原始代码更改为使用 .isEmpty,因为这是 SwiftLint 建议的做法。
    • 不要使用这个扩展,太可怕了。只需使用developer.apple.com/documentation/swift/array/2945493-contains
    • 当没有语言历史概念的人做出这样的判断时非常棒。请注意“为 Swift 2/3 更新”部分,此时 contains 被添加到语言中。
    【解决方案4】:

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

    例如:

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

    那么你可以这样做:

    cupArray.contains(myCup)
    

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

    【讨论】:

      【解决方案5】:

      我使用了过滤器。

      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 中的一行,在该字段上使用过滤器。
      • 过滤器效率低下,因为它总是循环遍历所有元素,而不是在找到元素时立即返回。最好改用 find()。
      【解决方案6】:

      (斯威夫特 3)

      检查数组中是否存在元素(满足某些条件),如果存在,则继续处理第一个这样的元素

      如果意图是:

      1. 检查一个元素是否存在于数组中(/满足一些布尔标准,不一定是相等测试),
      2. 如果是这样,请继续使用第一个此类元素,

      那么contains(_:) 的替代方案是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

      与上述类似的用例是删除满足给定谓词的第一个元素。为此,可以使用Collectionindex(where:) 方法(可随时用于数组集合)来查找满足谓词的第一个元素的索引,然后可以将索引与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:) 返回) 使用来自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 实例),因此使用谓词查找给定成员有点过分,因为我们可能只是使用更简单的 @ 来测试相等性987654350@方法如@DogCoffee's answer所示。但是,如果将上述查找和删除方法应用于 Person 示例,则将 index(where:) 与谓词一起使用是合适的(因为我们不再测试相等性,而是满足提供的谓词)。

      【讨论】:

      • 如何从数组中删除 firstSuchElement?
      • @i6x86 感谢您的提问。我用如何删除元素(以及如何删除和捕获已删除元素)的示例更新了我的答案。
      【解决方案7】:

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

      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]
      • @DanBeaulieu 执行let result = elements.filter { $0==5 }.first 之类的操作应该可以满足您的需求。
      • @davetw12 否。这将不必要地迭代整个集合。最好使用first(where: predicate)
      【解决方案8】:

      一个包含等于的属性的数组

      yourArray.contains(where: {$0.propertyToCheck == value })
      

      返回布尔值。

      【讨论】:

        【解决方案9】:

        斯威夫特 4/5

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

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

        【讨论】:

        • 这将不必要地迭代整个集合。这绝对是错误的做法。
        【解决方案10】:

        从 Swift 2.1 开始,NSArray 具有 containsObject,可以像这样使用:

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

        【讨论】:

        • 其实这是一个 NSArray。不是一个快速数组
        • 是的,但是您可以将您的 swift 数组临时转换为 NSArray: if let tempNSArrayForChecking = mySwiftArray as NSArray?其中 tempNSArrayForChecking.containsObject(objectImCheckingFor) {//myArray 有对象 }
        【解决方案11】:

        数组

        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
        

        【讨论】:

          【解决方案12】:

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

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

          【讨论】:

            【解决方案13】:

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

            var arrelemnts = ["sachin", "test", "test1", "test3"]
            
             if arrelemnts.contains("test"){
                print("found")   }else{
                print("not found")   }
            

            【讨论】:

              【解决方案14】:

              这是我刚刚编写的小扩展,用于检查我的委托数组是否包含委托对象(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
                  }
              }
              

              如果您知道如何优化此代码,请告诉我。

              【讨论】:

                【解决方案15】:

                斯威夫特

                如果你不使用对象,那么你可以使用这个代码来包含。

                let elements = [ 10, 20, 30, 40, 50]
                
                if elements.contains(50) {
                
                   print("true")
                
                }
                

                如果你在 swift 中使用 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")
                
                 }
                

                【讨论】:

                  【解决方案16】:

                  像这样使用哈希表来完成这项工作怎么样?

                  首先,创建一个“哈希映射”泛型函数,扩展 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
                  

                  【讨论】:

                    【解决方案17】:

                    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
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2021-12-03
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-01-30
                      • 1970-01-01
                      • 2017-02-10
                      • 2010-12-30
                      • 1970-01-01
                      • 2019-04-08
                      相关资源
                      最近更新 更多