В Котлине, как проверить содержит то или иное значение?

в Котлине мы можем сделать:

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

но если я хочу проверить, если 2 или 3 в arr, каков самый идиоматический способ сделать это, кроме:

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

6 ответов


Я хотел бы использовать any () метод расширения:

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

таким образом, вы пересекаете массив только один раз, и вы не создаете экземпляр set только для того, чтобы проверить, пуст он или нет (как в одном из других ответов на этот вопрос).


можно использовать пересечение метод, он принимает iterable как paramter и возвращает набор, содержащий только элементы, которые находятся как в вашей коллекции, так и в iterable вы предоставили. Тогда на этом наборе вам просто нужно сделать проверку размера.

вот пример:

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

это самый короткий и самый идиоматический способ, который я могу придумать, используя any и in:

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

array.any { it in values }

конечно, вы можете использовать ссылка на функцию для in оператор как это:

array.any(values::contains)

Я использую setOf для первой коллекции, потому что порядок не имеет значения.

Edit: я перешел values и array из-за Алекс.dorokhow ответ. Порядок не имеет значения для проверки но для производительности.


ОП хотел самый идиоматический способ решения этой проблемы. Если вы после более эффективного способа пойти на ада.


объединение решений @aga и @willi-mentzel для повышения эффективности и динамического набора проверенных значений:

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

в этом случае массив будет повторяться полностью только один раз (в худшем случае не более).

это более эффективно, чем (предложено @WilliMentzel):

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

где массив будет повторяться set.граф!--10--> раз в худшем случае.

отметим, что Set.содержит имеет O (1) сложность, но IntArray:: содержит имеет O (N).

конечно, эта оптимизация имеет смысл только если набор или массив достаточно большой.


Я думаю, что наиболее читабельно написать заявление наоборот:

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

возможно даже использовать диапазоны в определенных сценариях:

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

В конце концов, ваше решение выглядит довольно хорошо для меня уже. Хотя и не используя функциональность fancy library.


Если это не имеет значения, если оба происходят в массиве, вы можете использовать when такое выражение:

when (arr) {
    2,3  --> println("in list")
    else --> println("not in list")
}

это будет печатать "в списке", когда 2 или 3 находятся в списке.

дополнительные сведения об управлении потоком см. В разделе здесь