요소가 배열에 있는지 확인하는 방법


475

Swift에서 배열에 요소가 있는지 어떻게 확인할 수 있습니까? 엑스 코드에 대한 어떤 제안이없는 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 { }충분하지 않습니까?
Martin R

1
나는 더 깨끗한 것을 원했지만 좋지 않습니다. 설명서 나 책에서 아직 아무것도 찾지 못했습니다.
jaredsmith 2016 년

답변:


860

스위프트 2, 3, 4, 5 :

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

contains()프로토콜 확장 방법 입니다SequenceType (시퀀스의 Equatable요소)가 아니라 이전 릴리즈로서 세계 방법.

비고 :

스위프트 구버전 :

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

4
이런 종류의 전역 함수에 대한 문서가 있습니까?
Rivera

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

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

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

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

1
.contains는
익숙

4
구문을 세분화하여 설명 할 수 있습니까? 나는이 형식을 본 적이 없으며 한 번에 많은 고급 작업이 발생합니다!
공격자

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 {
}

희망이 도움이됩니다.


스위프트 2 업데이트

기본 구현을위한 Hurray!

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

나는 당신이 모든 종류의 것들에 사용할 수 있기 때문에 필터 솔루션을 좋아합니다. 예를 들어, 목록에 이미 문자열 값을 포함하는 필드 중 하나가있는 항목이 있는지 확인하려고 반복하고 반복하는 코드를 이식하고있었습니다. 해당 필드에 필터를 사용하는 Swift 의 한 줄 입니다.
Maury Markowitz

필터는 요소가 발견되면 즉시 반환하는 대신 항상 모든 요소를 ​​반복하기 때문에 비효율적입니다. 대신 find ()를 사용하는 것이 좋습니다.
Thorsten

19

(스위프트 3)

요소가 배열에 존재하는지 확인 (일부 기준 충족) 하고있는 경우 첫 번째 요소로 작업을 진행하십시오.

의도가 다음과 같은 경우 :

  1. 요소가 배열에 존재하는지 확인하려면 (항상 테스트가 아닌 일부 부울 기준을 충족시킵니다),
  2. 그렇다면 첫 번째 요소로 진행하여 작업하십시오.

그런 다음에 대한 대안 contains(_:)청사진을로는 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, 이는 필터를 통과하는 (가능한) 제 1 요소를 추출하기 전에 전체 어레이를 통과하기 때문이다.


요소가 배열에 존재하는지 확인하고 (일부 기준 충족), 존재하는 경우 첫 번째 요소를 제거하십시오

아래의 의견은 다음을 쿼리합니다.

firstSuchElement어레이에서를 제거하려면 어떻게 해야합니까?

위와 유사한 유스 케이스 는 주어진 술어를 충족시키는 첫 번째 요소 를 제거 하는 것입니다. 이렇게하기 위해, index(where:)방법 Collection(배열 컬렉션에 용이하게 사용할 수 있음)의 인덱스가 함께 사용될 수있다 whereafter 술어를 만족 첫번째 요소의 인덱스 찾기 위해 사용될 수있는 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인스턴스)이므로 주어진 멤버를 찾기 위해 술어를 사용하는 것은 다소 과도합니다 index(of:). @ DogCoffee의 답변에 표시된 것처럼 더 간단한 방법을 사용하여 동등성을 테스트 할 수 있기 때문입니다. . Person그러나 위의 찾기 및 제거 방법을 예제에 적용하는 경우 index(where:)술어와 함께 사용 하는 것이 적절합니다 (더 이상 동등성을 테스트하지 않고 제공된 술어를 충족시키기 위해).


배열에서 firstSuchElement를 어떻게 제거 할 수 있습니까?
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는 고유하므로 하나의 결과 만있을 수 있습니다. 하나의 결과 만 반환하는 방법이 있습니까? 지금 검색 결과 [0]을 사용하고 있습니다
단 보리

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부터 NSArray는 containsObject다음과 같이 사용할 수 있습니다.

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

4
실제로 그것은 NSArray를위한 것입니다. 빠른 배열이 아님
Tycho Pandelaar

예, 그러나 신속 배열을 NSArray로 임시 변환 할 수 있습니다. if tempNSArrayForChecking = mySwiftArray를 NSArray로 설정 하시겠습니까? 여기서 tempNSArrayForChecking.containsObject (objectImCheckingFor) {// myArray에 객체가 있습니다}
Vitalii

4

누군가가 indexPath선택된 것들 중 하나인지 ( 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

이 작업에 해시 테이블을 사용하는 것은 어떻습니까?

먼저 시퀀스 프로토콜을 확장하여 "해시 맵"일반 함수를 만듭니다.

extension Sequence where Element: Hashable {

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

이 확장은 배열의 항목이 정수 또는 문자열과 같이 해시 가능을 준수하는 한 작동합니다.

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.