2017-04-05 1 views
1

Je voudrais tester si un nombre (n) ou plus d'éléments d'une séquence ou d'une collection retournera vrai une fois transmis à un fonction. Je ne m'intéresse pas au nombre d'éléments qui retourneraient vrai, juste si n ou plus le ferait ou non. Je peux obtenir le bon résultat avec ce code:Comment tester si n ou plusieurs éléments d'une collection ou d'une séquence réussissent une condition sans traiter chaque élément

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

Mais la fonction test est appelée une fois pour chaque élément de collection. Y a-t-il une meilleure façon (ou peut-être paresseuse) de faire cela?

je peux le faire manuellement mais itérer sur quelque chose de collection comme:

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

Mais la première voie semble beaucoup plus élégant. Je comprends que, dans le pire des cas, chaque élément devrait être testé. Je veux juste éviter les calculs inutiles si possible.

Répondre

2

Dans le cas n = 1 (vérifier si au moins un élément de la séquence passe le test), vous pouvez utiliser contains(where:) avec un prédicat:

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

ou juste

let result = sequence.contains(where: test) 

Dans le cas général (vérifiez si la séquence contient au moins un nombre donné d'éléments correspondants) vous pouvez utiliser un filtre paresseux. Exemple:

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) 

Si vous ajoutez une instruction d'impression à la fonction isEven alors vous verrez qu'il ne soit pas appelé plus souvent que nécessaire.

+0

Excellent, merci. Y at-il quelque chose d'aussi élégant si j'essayais de trouver si au lieu d'un ou plusieurs, il y en avait deux ou plus? –

+1

@JoshParadroid: Voir mise à jour. –

+0

C'est incroyable. Je n'aurais pas pensé à ça. Aurais-je raison de penser que c'est le dropFirst (3) qui fait que les chiffres sont évalués? Merci beaucoup. –