web-dev-qa-db-ja.com

Swiftでリストアイテムのインデックスを見つける方法は?

リストを検索してアイテムインデックスを見つけようとしています。誰かがそれを行う方法を知っていますか?

list.StartIndexlist.EndIndexがあるようですが、私はpythonのlist.index("text")のようなものが欲しいです。

394
Chéyo

Swiftはいくつかの点でオブジェクト指向よりも機能的であるため(そして、配列はオブジェクトではなく構造体です)、配列を操作するために関数 "find"を使います。

let arr:Array = ["a","b","c"]
find(arr, "c")!              // 2
find(arr, "d")               // nil

Swift 2.0へのアップデート:

古いfind関数はSwift 2.0ではサポートされなくなりました!

Swift 2.0では、Arrayは、(CollectionTypeが実装している)Arrayの拡張で定義された関数を使用して、要素のインデックスを見つけることができます。

let arr = ["a","b","c"]

let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil

さらに、述語を満たす配列の最初の要素を見つけることは、CollectionTypeの別の拡張によってサポートされています。

let arr2 = [1,2,3,4,5,6,7,8,9,10]
let indexOfFirstGreaterThanFive = arr2.indexOf({$0 > 5}) // 5
let indexOfFirstGreaterThanOneHundred = arr2.indexOf({$0 > 100}) // nil

findが以前に行ったように、これら2つの関数はオプションの値を返すことに注意してください。

Swift 3.0用のアップデート:

IndexOfの構文が変更されたことに注意してください。 Equatableに準拠するアイテムには、次のものを使用できます。

let indexOfA = arr.index(of: "a")

このメソッドの詳細なドキュメントは https://developer.Apple.com/reference/Swift/array/1689674-index にあります。

Equatableに準拠していない配列項目の場合は、index(where:)を使用する必要があります。

let index = cells.index(where: { (item) -> Bool in
  item.foo == 42 // test if this is the item you're looking for
})

Swift 4.2用の更新:

Swift 4.2では、indexは使用されなくなりましたが、より明確にするためにfirstIndexlastIndexに分けられています。つまり、アイテムの最初のインデックスと最後のインデックスのどちらを探しているかによって異なります。

let arr = ["a","b","c","a"]

let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3
750
sschuth

tl; dr:

クラスの場合、次のものを探しているかもしれません。

let index = someArray.firstIndex{$0 === someObject}

完全な答え:

参照型(class)では、identity比較を実行することをお勧めします。この場合、述語クロージャで=== identity演算子を使用するだけで済みます。


Swift 5、Swift 4.2:

let person1 = Person(name: "John")
let person2 = Person(name: "Sue")
let person3 = Person(name: "Maria")
let person4 = Person(name: "Loner")

let people = [person1, person2, person3]

let indexOfPerson1 = people.firstIndex{$0 === person1} // 0
let indexOfPerson2 = people.firstIndex{$0 === person2} // 1
let indexOfPerson3 = people.firstIndex{$0 === person3} // 2
let indexOfPerson4 = people.firstIndex{$0 === person4} // nil

上記の構文は末尾のクロージャー構文を使用し、次と同等であることに注意してください。

let indexOfPerson1 = people.firstIndex(where: {$0 === person1})


Swift 4/Swift 3-以前はindexと呼ばれていた関数

Swift 2-indexOfと呼ばれていた関数

*関連する有用な comment に注意してください paulbaileyclassを実装するEquatable型について、比較する必要があるかどうかを検討する必要がある場合===identity operator)または==equality operator)を使用します。 ==を使用して一致させる場合、他の人が提案したメソッド(people.firstIndex(of: person1))を使用できます。

186

クロージャーを持つ配列をfilterすることができます。

var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 }  // <= returns [3]

そして、あなたは配列を数えることができます:

filtered.count // <= returns 1

そのため、 if の場合、これらの要素を組み合わせて配列に要素を含めることができます。

myList.filter { $0 == 3 }.count > 0  // <= returns true if the array includes 3

あなたが位置を見つけたいのなら、私は空想的な方法を見ませんが、あなたは確かにこのようにそれをすることができます:

var found: Int?  // <= will hold the index if it was found, or else will be nil
for i in (0..x.count) {
    if x[i] == 3 {
        found = i
    }
}

_編集_

私たちが行っている間、楽しい練習のためにArrayメソッドを持つためにfindを拡張しましょう:

extension Array {
    func find(includedElement: T -> Bool) -> Int? {
        for (idx, element) in enumerate(self) {
            if includedElement(element) {
                return idx
            }
        }
        return nil
    }
}

今、これを行うことができます。

myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found
80
gwcoffey

スイフト5

func index(of element: Element) -> Int?

var alphabets = ["A", "B", "E", "D"]

例1

let index = alphabets.index(where: {$0 == "A"})

例2

if let i = alphabets.index(of: "E") {
    alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
24
Saranjith

indexOf()は完璧に動作しますが、 はインデックスを1つだけ返します。

私はある条件を満たす要素のためのインデックスの配列を得るためのエレガントな方法を探していました。

それができる方法は次のとおりです。

スイフト3:

let array = ["Apple", "dog", "log"]

let indexes = array.enumerated().filter {
    $0.element.contains("og")
    }.map{$0.offset}

print(indexes)

スイフト2:

let array = ["Apple", "dog", "log"]

let indexes = array.enumerate().filter {
    $0.element.containsString("og")
    }.map{$0.index}

print(indexes)
23

カスタムクラスの場合は、Equatableプロトコルを実装する必要があります。

import Foundation

func ==(l: MyClass, r: MyClass) -> Bool {
  return l.id == r.id
}

class MyClass: Equtable {
    init(id: String) {
        self.msgID = id
    }

    let msgID: String
}

let item = MyClass(3)
let itemList = [MyClass(1), MyClass(2), item]
let idx = itemList.indexOf(item)

printl(idx)
12
ZYiOS

Swift 2用のアップデート:

sequence.contains(element) :指定されたシーケンス(配列など)に指定された要素が含まれる場合はtrueを返します。

スイフト1:

要素が配列内に含まれているかどうかをチェックするだけの場合は、つまりブール値のインジケータを取得するだけの場合は、contains(sequence, element)ではなくfind(array, element)を使用します。

contains(sequence、element) :指定されたシーケンス(配列など)に指定された要素が含まれる場合はtrueを返します。

下記の例を参照してください。

var languages = ["Swift", "Objective-C"]
contains(languages, "Swift") == true
contains(languages, "Java") == false
contains([29, 85, 42, 96, 75], 42) == true
if (contains(languages, "Swift")) {
  // Use contains in these cases, instead of find.   
}
9
Zorayr

Swift 4.配列に[String:AnyObject]型の要素が含まれている場合だから、要素のインデックスを見つけるために以下のコードを使う

var array = [[String: AnyObject]]()// Save your data in array
let objectAtZero = array[0] // get first object
let index = (self.array as NSArray).index(of: objectAtZero)

またはあなたが辞書からのキーに基づいてインデックスを見つけたい場合。ここでの配列はModelクラスのオブジェクトを含み、私はidプロパティにマッチしています。

let userId = 20
if let index = array.index(where: { (dict) -> Bool in
       return dict.id == userId // Will found index of matched id
}) {
print("Index found")
}
5
GSK

この解決策のどれでも私のために働く

これは私がSwift 4に持っている解決策です:

let monday = Day(name: "M")
let tuesday = Day(name: "T")
let friday = Day(name: "F")

let days = [monday, tuesday, friday]

let index = days.index(where: { 
            //important to test with === to be sure it's the same object reference
            $0 === tuesday
        })
4
Kevin ABRIOUX

DataModel配列をトラバースする場合は、 Swift 4 で、データモデルがEquatable Protocolに準拠していることを確認し、lhs = rhsメソッドを実装してください。

class Photo : Equatable{
    var imageURL: URL?
    init(imageURL: URL){
        self.imageURL = imageURL
    }

    static func == (lhs: Photo, rhs: Photo) -> Bool{
        return lhs.imageURL == rhs.imageURL
    }
}

その後、

let index = self.photos.index(of: aPhoto)
4
Naishta

Swift 2(Xcode 7)では、ArrayindexOf プロトコルによって提供される CollectionType メソッドを含みます。 (実際には、2つのindexOfメソッド - 引数を一致させるために等価性を使用するもの、および もう1つ クロージャを使用するもの)

Swift 2より前では、コレクションのようなジェネリック型がそれらから派生した具象型(配列のような)のためのメソッドを提供する方法はありませんでした。つまり、Swift 1.xでは、 "index of"はグローバル関数です。また、Swift 1.xでは、このグローバル関数はfindと呼ばれています。

indexOfObject...からのNSArrayメソッド、またはSwift標準ライブラリに同等のものがないFoundationからのより洗練された検索方法のいずれかを使用することも可能です(ただし必須ではありません)。単にimport Foundation(またはFoundationを他動的にインポートする他のモジュール)を使い、ArrayNSArrayにキャストすれば、NSArrayでさまざまな検索方法を使うことができます。

4
rickster

関数ライブラリDollarを使って配列のindexOfを次のようにすることもできます http://www.dollarswift.org/#indexof-indexof

$.indexOf([1, 2, 3, 1, 2, 3], value: 2) 
=> 1
2
Encore PTL

スイフト2.1

var array = ["0","1","2","3"]

if let index = array.indexOf("1") {
   array.removeAtIndex(index)
}

print(array) // ["0","2","3"]

スイフト3

var array = ["0","1","2","3"]

if let index = array.index(of: "1") {
    array.remove(at: index)
}
array.remove(at: 1)
2
Luca Davanzo

まだSwift 1.xで作業している場合

それでは、

let testArray = ["A","B","C"]

let indexOfA = find(testArray, "A") 
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")
2
iCyberPaul

スイフト4

CardButtonsという名前の配列の番号をcardNumberに格納したいとしましょう。この方法でそれを実行できます。

let cardNumber = cardButtons.index(of: sender)

送信者はあなたのボタンの名前です

1
Arturo

スイフト4

参照タイプの場合

extension Array where Array.Element: AnyObject {

    func index(ofElement element: Element) -> Int? {
        for (currentIndex, currentElement) in self.enumerated() {
            if currentElement === element {
                return currentIndex
            }
        }
        return nil
    }
}
0
Menno

Swift 3では、単純な関数を使うことができます

func find(objecToFind: String?) -> Int? {
   for i in 0...arrayName.count {
      if arrayName[i] == objectToFind {
         return i
      }
   }
return nil
}

これは数字の位置を与えるので、あなたは次のように使うことができます。

arrayName.remove(at: (find(objecToFind))!)

役に立つことを願っています

0
Marco