Swift에서 목록 항목의 색인을 찾는 방법은 무엇입니까?


443

item index를 검색 하여을 (를) 찾으려고합니다 list. 아무도 그 방법을 알고 있습니까?

나는이 참조 list.StartIndex하고 list.EndIndex있지만 파이썬의 뭔가를하려는 list.index("text").

답변:


823

swift는 객체 지향 (그리고 배열은 객체가 아닌 구조체입니다)보다 기능면에서 더 뛰어나므로 "find"함수를 사용하여 배열에서 작동하여 선택적 값을 반환하므로 nil 값을 처리 할 준비를하십시오.

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

Swift 2.0 업데이트 :

findSwift 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는 이전 과 마찬가지로 선택적 값을 반환합니다 .

스위프트 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 업데이트 :

스위프트 4.2으로, index더 이상 사용되지 않고로 분리 firstIndex하고 lastIndex보다 명확한 설명. 따라서 항목의 첫 번째 인덱스 또는 마지막 인덱스를 찾고 있는지에 따라

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

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

22
찾기 기능에 대해 어디서 배웠습니까? "찾기"또는 기타 전역 기능에 대한 문서를 찾을 수 없습니다.
Johannes

14
OOP 세계에서 왔을 때, 이런 종류의 자유 부동 함수를 어떻게 찾습니까?
Rudolf Adamkovič

4
그들은 문서화되지 않은 것 같습니다. 목록 은 actualswift.com/2014/06/14/… 를 참조하십시오 (그러나 목록이 완전한지 또는 최신인지 확인하지는 않았습니다).
Sebastian Schuth

5
Johannes와 @Rudolf-Dash.app를 사용하십시오. 문서를 찾아보기위한 OS X 앱입니다. 모든 자유 부동 함수 목록이있는 Swift에 대한 언어 참조가 있습니다. 필터링 및 검색이 쉽습니다. 그것 없이는 살 수 없습니다.
Bjorn

4
참고 : indexOf직접 정의한 구조체를 사용 하는 경우 구조체는 Equatable프로토콜 을 준수해야 합니다.
Matthew Quiros

202

tl; dr :

수업의 경우 다음을 찾고있을 수 있습니다.

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

전체 답변 :

참조 유형 ( class)을 사용하면 ID 비교 를 수행 할 수 있다고 언급 할 가치가 있다고 생각합니다 .이 경우 ===술어 클로저에서 ID 연산자 를 사용해야합니다 .


스위프트 5, 스위프트 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})


스위프트 4 / 스위프트 3-호출되는 함수 index

스위프트 2-호출 된 함수 indexOf

* 구현 하는 유형 에 대해 paulbailey 의 관련적이고 유용한 의견주목하십시오 . 여기서 ( identity operator) 또는 ( equality operator)를 사용하여 비교해야하는지 고려해야합니다 . 를 사용하여 일치하기로 결정한 경우 다른 사람이 제안한 방법 ( ) 만 사용하면됩니다 .classEquatable=======people.firstIndex(of: person1)


6
이것은 .indexOf (x)가 왜 작동하지 않는지 궁금해하는 사람들에게 유용한 게시물입니다.
Maury Markowitz

1
이것에 너무 감사하지만 전혀 나에게 분명하지 않습니다. 설명서를 보았고 참조 유형에서 indexOf를 사용할 때 왜 술어 클로저가 필요한지 이해하지 못합니까? indexOf가 이미 자체적으로 참조 유형을 처리 할 수 ​​있어야합니다. 값 유형이 아닌 참조 유형임을 알아야합니다.
Chris

7
경우에 Person구현 된 Equatable프로토콜을, 이것은 필요하지 않을 것입니다.
paulbailey

2
나는 받고있다 : Binary operator '===' cannot be applied to operands of type '_' and 'Post', Post내 구조는 ... 어떤 생각입니까?
David Seek

@DavidSeek structs(및 enums)는 참조 유형이 아닌 값 유형입니다. 참조 유형 (예 :) 만 classID 비교 논리 ( ===)를 갖습니다 . 무엇을 해야할지에 대한 다른 답변을 확인하십시오 structs(기본적으로 단순히 array.index(of: myStruct)유형을 myStruct준수 하는지 확인하십시오 Equatable( ==)).
Nikolay Suvandzhiev

81

filter클로저 가 있는 배열은 다음과 같습니다.

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

그리고 당신은 배열을 셀 수 있습니다 :

filtered.count // <= returns 1

그래서 당신은 확인할 수 있는 경우 배열이 결합하여 요소를 포함 :

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

funsies의 경우 원하는 것을 수행 Array하는 find메소드 를 갖도록 내장 을 확장하는 또 다른 예제를 추가했습니다 . 이것이 좋은 방법인지는 아직 모르겠지만 깔끔한 실험입니다.
gwcoffey 2018 년

2
docs에 따라 ++ idx를 사용해야한다는 점을 지적하고 싶다. "i ++의 특정 동작이 필요하지 않은 한, 모든 경우에 ++ i와 --i를 사용하는 것이 좋습니다. i를 수정하고 결과를 반환하는 동작 "
로건

잘 했어 이 게시물을 게시 enumerate할 때 더 이상 적용되지 않도록 사용 하도록 수정 했지만 절대적으로 옳습니다.
gwcoffey 2016 년

예, 나는 그것을 겪을 때의 예 중 하나에서 그것을 알아 차리는 것을 기억했습니다. 지금 습관에 자신을 설정하려고 :)
Logan

4
이것이 Swift 2 / XCode 7에서 작동하려면 다음과 같이 수정해야합니다. (includedElement : T-> Bool)을 (includedElement : Element-> Bool)로 바꾸고 enumerate (self)를 self.enumerate로 변경하십시오.
Scooter

35

스위프트 5

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

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

예 1

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

예 2

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

25

indexOf()완벽하게 작동 하지만 하나의 인덱스 만 반환합니다.

조건을 만족시키는 요소에 대한 인덱스 배열을 얻는 우아한 방법을 찾고있었습니다.

수행 방법은 다음과 같습니다.

스위프트 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)

12

사용자 정의 클래스의 경우 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)

9

스위프트 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.   
}

7

에서 스위프트 4.2

:)이있는 .index ( 변경되었습니다 .firstIndex (여기서 :)

array.firstIndex(where: {$0 == "person1"})

6

스위프트 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)

또는 Dictionary의 키를 기준으로 색인을 찾으려면. 여기 배열에는 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")
    }
OR
      let storeId = Int(surveyCurrent.store_id) // Accessing model key value
      indexArrUpTo = self.arrEarnUpTo.index { Int($0.store_id) == storeId }! // Array contains models and finding specific one

4

스위프트 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)

3
당신은 돌연변이 let array? 의 사용 self도 의심 스럽다.
Chéyo

4

에서 스위프트 4 당신이 당신의 DataModel이 배열을 통해 통과하는 경우, 방법을 우 = 좌변을 구현, Equatable 의정서 확인 데이터 모델에 부합 함을 선언을하고, 그런 다음에야 당신은 '의 (있는 .index "를 사용할 수 있습니다. 예를 들어

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

Swift 2 (Xcode 7 사용) Array에는 프로토콜에서 indexOf제공 하는 방법이 포함되어 CollectionType있습니다. 실제로 두 가지 indexOf방법 , 즉 하나는 인수를 일치시키기 위해 동등을 사용하고 다른 하나 는 클로저를 사용합니다.

Swift 2 이전에는 컬렉션과 같은 일반 유형에서 파생 된 구체적인 유형 (예 : 배열)에 대한 메소드를 제공 할 방법이 없었습니다. Swift 1.x에서 "index of"는 전역 함수입니다 ... 그리고 Swift 1.x에서도 전역 함수의 이름이 바뀌 었습니다 find.

... 또는 Swift 표준 라이브러리에 해당하지 않는 Foundation의 다른 고급 검색 indexOfObject방법 NSArray중 하나 의 방법 을 사용할 수도 있습니다 (필수는 아님) . 그냥 import Foundation(또는 이적으로 재단을 가져 또 다른 모듈), 당신의 캐스팅 ArrayNSArray, 당신은에 많은 검색 방법을 사용할 수 있습니다 NSArray.


4

이 솔루션은 저에게 효과적입니다.

이것이 스위프트 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
        })


2

여전히 Swift 1.x에서 작업중인 경우

그런 다음 시도하십시오

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

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

1

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))!)

유용하기를 바랍니다


1

스위프트 4

cardButtons라는 배열의 숫자를 cardNumber에 저장한다고 가정하면 다음과 같이 할 수 있습니다.

let cardNumber = cardButtons.index(of: sender)

발신자는 버튼 이름입니다.


0

스위프트 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

Swift 4/5에서 찾기 색인에 "firstIndex"를 사용하십시오.

let index = array.firstIndex{$0 == value}

0

누군가이 문제가있는 경우

Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'

jsut이 작업을 수행

extension Int {
    var toInt: Int {
        return self
    }
}

그때

guard let finalIndex = index?.toInt else {
    return false
}

0

에 대한 (>= swift 4.0)

오히려 매우 간단합니다. 다음 Array목표를 고려하십시오 .

var names: [String] = ["jack", "rose", "jill"]

element의 인덱스를 얻으려면 다음 rose을 수행하면됩니다.

names.index(of: "rose") // returns 1

노트 :

  • Array.index(of:)을 반환합니다 Optional<Int>.

  • nil 요소가 배열에 존재하지 않음을 의미합니다.

  • 반환 된 값을 강제로 줄 바꿈 해제하거나 또는 if-let옵션을 사용하여 돌아올 수 있습니다 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.