2017-04-05 4 views
1

시퀀스 또는 컬렉션의 숫자 (n) 이상 요소가 true를 반환하는지 테스트하고 싶습니다. 기능. 나는 n 또는 그 이상이 true 일 때, 얼마나 많은 원소가 true를 반환 할 것인지 관심이 없다. 이 코드로 올바른 결과를 얻을 수 있습니다 :컬렉션 또는 시퀀스의 n 개 이상의 요소가 모든 요소를 ​​처리하지 않고 조건을 전달하는지 테스트하는 방법

let result = collection.filter { test($0) }.count > (n-1) 

그러나 test 기능은 collection의 각 요소에 대해 한 번 호출된다. 이 작업을 수행하는 데 더 나은 (또는 '게으른') 방법이 있습니까?

나는이 수동으로하지만, 같은 컬렉션 뭔가 반복 수행 할 수 있습니다

let result:Bool = { 
    var nCount = 0 
    for object in collection { 
     if test(object) { 
      nCount = nCount + 1 
      if nCount >= n { 
       return true 
      } 
     } 
    } 
    return false 
}() 

그러나 첫 번째 방법은 훨씬 더 우아한 보인다.

최악의 시나리오에서 모든 요소를 ​​테스트해야한다는 것을 알고 있습니다. 가능한 경우 불필요한 계산을 피하고 싶습니다.

let result = sequence.contains(where: { test($0) }) 

하거나

let result = sequence.contains(where: test) 

물 :

답변

2
경우

N = 1는 술어 contains(where:)를 사용할 수있다 (시퀀스 중 적어도 하나 개의 원소 테스트를 통과하면 확인) 일반적인 경우 (시퀀스에 적어도 일치하는 항목 수가 포함되어 있는지 확인) 지연 필터를 사용할 수 있습니다. 예 :

func isEven(_ i : Int) -> Bool { return i % 2 == 0 } 

let numbers = Array(1...10) 

let atLeast4EvenNumbers = !numbers.lazy.filter(isEven).dropFirst(3).isEmpty 
print(atLeast4EvenNumbers) 

당신이 isEven 함수에 인쇄 문을 추가하는 경우 다음이 필요한 것보다 더 자주 호출되지 않습니다 를 볼 수 있습니다.

+0

우수 감사합니다. 만약에 하나 이상의 것이 아니라 두 개 또는 그 이상이 발견된다면 너무 우아합니다. –

+1

@JoshParadroid : 업데이트를 참조하십시오. –

+0

놀랍습니다. 나는 그런 생각을하지 않았을 것이다. 내가 dropFirst (3)가 그 숫자를 평가하게 만들었다 고 생각하는 것이 옳은가? 많은 감사합니다. –

관련 문제