web-dev-qa-db-fra.com

En Kotlin, comment vérifier contient l'une ou l'autre valeur?

À Kotlin, nous pouvons faire:

val arr = intArrayOf(1,2,3)
if (2 in arr)
   println("in list")

Mais si je veux vérifier si 2 ou 3 sont dans arr, quelle est la manière la plus idiomatique de procéder autrement que:

if (2 in arr || 3 in arr)
   println("in list")
9
ADev

J'utiliserais la méthode any () extension:

arrayOf(1, 2, 3).any { it == 2 || it == 3 }

De cette façon, vous ne parcourez le tableau qu'une seule fois et vous ne créez pas d'occurrence définie pour vérifier si elle est vide ou non (comme dans l'une des réponses à cette question).

15
aga

Vous pouvez utiliser la méthode intersect , elle prend iterable en tant que paramètre et renvoie un ensemble contenant uniquement les éléments que vous avez fournis. Ensuite, sur cet ensemble, il vous suffit de vérifier la taille.

Voici un échantillon:

val array1 = arrayOf(1, 2, 3, 4, 5, 6)
val array2 = arrayOf(2, 5)

// true if array1 contains any of the items from array2
if(array1.intersect(array2.asIterable()).isNotEmpty()) {
    println("in list")
}
8
Mateusz

C’est le moyen le plus court et le plus idiomatique auquel je puisse penser en utilisant any et in:

val values = setOf(2, 3)
val array = intArrayOf(1, 2, 3)

array.any { it in values }

Bien sûr, vous pouvez également utiliser un opérateur { référence de fonction pour l'opérateur in :

array.any(values::contains)

J'utilise setOf pour la première collection car l'ordre n'a pas d'importance.

Edit: J'ai changé values et array, à cause de la réponse de alex.dorokhow . L'ordre n'a pas d'importance pour que le contrôle fonctionne, mais pour la performance.


Le PO voulait la manière la plus idiomatique de résoudre ce problème. Si vous recherchez un moyen plus efficace, optez pour réponse d'Ada .

6
Willi Mentzel

Combinaison des solutions @aga et @ willi-mentzel pour une meilleure efficacité et un ensemble dynamique de valeurs vérifiées:

val numbers = setOf(2, 3)
arrayOf(1, 2, 3).any(numbers::contains)

Dans ce cas, le tableau sera itéré complètement une seule fois (au plus, dans le pire des cas).

Ceci est plus efficace que (suggéré par @WilliMentzel):

numbers.any(arrayOf(1, 2, 3)::contains) // don't do that!

Où le tableau sera itéré set.count times dans le pire des cas.

Notez que Set.contains a O(1) complexité, mais IntArray :: contient a O (N).

Bien entendu, cette optimisation n’a de sens que si l’ensemble ou le tableau est suffisamment grand.

3
alex.dorokhov

Je pense qu'il est plus lisible d'écrire la déclaration dans l'autre sens:

val arr = intArrayOf(1,2,3)
val match = setOf(2, 3).any(arr::contains)

Il pourrait même être possible d'utiliser des plages dans certains scénarios:

val match = (2..3).any(arr::contains)

En fin de compte, votre solution me convient déjà très bien. Bien que n'utilisant pas les fonctionnalités de la bibliothèque de fantaisie. 

2
s1m0nw1

Une autre solution pratique n'est en réalité pas celle de Kotlin, mais l'utilisation de Java Collections.
Il est également bon de le savoir.

Collections.disjoint(Collection<?> c1, Collection<?> c2)

Renvoie {@code true} si les deux collections spécifiées ne contiennent aucun élément en commun.

@Test
fun disjointCollections() {
    val list = listOf(1, 2, 3)

    assertTrue(Collections.disjoint(list, listOf(7, 8)))
    assertFalse(Collections.disjoint(list, listOf(1)))
}
0
Leo Droidcoder