要素が配列にあるかどうかを確認する方法


475

Swiftでは、要素が配列に存在するかどうかをどのように確認できますか?Xcodeはのための任意の提案を持っていないcontainincludeまたはhas、そして本をクイック検索には何も上がっていません。これを確認する方法はありますか?findインデックス番号を返すメソッドがあることは知っていますが、ルビーのようなブール値を返すメソッドはあります#include?か?

私が必要とするものの例:

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

11
if find(elements, 5) != nil { }十分ではありませんか?
マーティンR

1
私はもっ​​とすっきりしたものを望んでいましたが、見栄えが良くありませんでした。ドキュメントや本にはまだ何も見つかりません。
jaredsmith 2014年

回答:


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
この種のグローバル関数に関するドキュメントはありますか?
Rivera

3
配列内の各項目(および検索している項目)のタイプがDictionary <String、AnyObject>である場合、これは機能するはずですか?それを達成しようとすると、コンパイル時エラーが発生します。
ppalancica 2015

7
@ppalancica:配列要素がEquatableプロトコルに準拠している必要があります(準拠していDictionary<String, AnyObject>ません)。contains()述語を取る(stackoverflow.com/questions/29679486/…と比較する)の2番目のバリアントがあります。おそらくそれを使用できます。例:if contains(array, { $0 == dict } ) ...
Martin R

ジェネリック配列から特定の要素を検索する方法は?[AnyObject]と言いますか?
Dhaval H. Nena

127

ここに来て、オブジェクトを見つけて配列からオブジェクトを削除した場合:

スウィフト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
質問に関連してお答えください。この質問は、配列内の要素を見つけることについてのみ尋ねており、それを削除または更新することはありません。別の質問をして、自分で答えることもできます。
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関数がの拡張メソッドのペアにArrayなり、次のいずれかを実行できるようになるため、拡張は不要になります。

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

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

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

10
検索が高速です。
ジムバルター2014年

1
ただし、慣れている内容によっては、.containsの方が直感的で覚えやすいと感じるかもしれません
Pirijan

4
構文を分解して説明できますか?私はこのフォーマットをこれまで見たことがなく、一度にたくさんの高度なことが起こっています!
アグレッサー、2014

40

カスタムクラスまたはカスタム構造体のインスタンスが配列に含まれているかどうかを確認する場合は、.contains(myObject)を使用する前に、Equatableプロトコルを実装する必要があります。

例えば:

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
}

フィルターソリューションは、あらゆる用途に使用できるので気に入っています。たとえば、リストに文字列値を含むフィールドの1つを持つアイテムがリストに既にあるかどうかを確認するためにループおよびループするコードを移植していました。これは、Swift の1行で、そのフィールドにフィルターを使用しています。
Maury Markowitz、2015年

filterは、要素が見つかるとすぐに戻るのではなく、常にすべての要素をループするため、非効率です。代わりにfind()を使用してください。
Thorsten

19

(スイフト3)

要素が配列に存在するかどうか(いくつかの基準を満たしているかどうか)を確認し、存在する場合は、そのような最初の要素の操作を続行します

意図が:

  1. 要素が配列内に存在するかどうかを確認するには(/等値テストではなく、いくつかのブール基準を満たします)、
  2. もしそうなら、最初のそのような要素に進んで作業し、

その後に代わるcontains(_:)blueprintedとしては、Sequenceにあるfirst(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(配列のコレクションですぐに使用できる)メソッドを使用して、述語を満たす最初の要素のインデックスを見つけます。その後、インデックスremove(at:)Arrayto(可能です。存在する場合)で使用できます。その要素を削除します。

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インスタンス)であるためindex(of:)@ DogCoffeeの回答に示されているように、単純なメソッドを使用して等価性をテストするだけなので、述語を使用して特定のメンバーを見つけるのはやややりすぎです。Personただし、上記の検索と削除のアプローチを例に適用する場合index(where:)は、述語と一緒に使用するのが適切です(等価性のテストは行われず、指定された述語を満たすため)。


配列からfirstSuchElementを削除するにはどうすればよいですか?
i6x86

@ i6x86質問ありがとうございます。要素を削除する方法(および削除された要素を削除してキャプチャする方法)の例を使用して、回答を更新しました。
dfri 2017

14

これを実現する最も簡単な方法は、配列でフィルターを使用することです。

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

result見つかった要素が存在する場合は要素があり、要素が存在しない場合は空になります。したがって、result空かどうかを確認するだけで、要素が配列に存在するかどうかがわかります。私は以下を使用します:

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

素晴らしいソリューション。したがって、このメソッドは配列を返します。ただし、これを使用して「id」を探しています。私のアプリケーションでは、dは一意であるため、結果は1つしかありません。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以降ではcontainsObject、NSArrayは次のように使用できます。

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

4
実際、これはNSArrayの場合です。迅速な配列ではない
Tycho Pandelaar 2016年

ええ、でも、swift配列をNSArrayに一時的に変換することができます。tempNSArrayForChecking= mySwiftArrayをNSArrayとすると、ここでtempNSArrayForChecking.containsObject(objectImCheckingFor){// myArrayにはオブジェクトがあります}
Vitalii

4

誰かがindexPath選択されたものの中にあるかどうかを誰かが見つけようとしている場合に備えて(a UICollectionViewまたはUITableView 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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.