Kotlinでは次のことができます。
val arr = intArrayOf(1,2,3)
if (2 in arr)
println("in list")
しかし、2 or 3がarr
にあるかどうかを確認したい場合、それを行うための最も慣用的な方法は何ですか:
if (2 in arr || 3 in arr)
println("in list")
any() 拡張メソッドを使用します:
arrayOf(1, 2, 3).any { it == 2 || it == 3 }
この方法では、配列を1回だけ走査し、空かどうかを確認するためだけにセットインスタンスを作成することはありません(この質問に対する他の回答のように)。
intersect メソッドを使用できます。パラメーターとしてiterableを受け取り、コレクションと指定した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
を使用します。
編集:alex.dorokhowの答え のため、values
とarray
を切り替えました。チェックが機能するためではなく、パフォーマンスのために順序は関係ありません。
OPは、これを解決する最も慣用的な方法を望んでいました。より効率的な方法を求めている場合は、 ada's answer に進んでください。
@agaと@ willi-mentzelのソリューションを組み合わせて、効率とチェック値の動的セットを改善します。
val numbers = setOf(2, 3)
arrayOf(1, 2, 3).any(numbers::contains)
この場合、配列は完全に1回だけ(最大で、最悪の場合)反復されます。
これは(@WilliMentzelが提案する)よりも効率的です。
numbers.any(arrayOf(1, 2, 3)::contains) // don't do that!
配列が反復される場所set.count最悪の場合。
Set.contains has O(1) complexityですが、IntArray :: contains has O(N)。
もちろん、この最適化は、セットまたは配列が十分に大きい場合にのみ意味があります。
ステートメントを逆に書くのが最も読みやすいと思います:
val arr = intArrayOf(1,2,3)
val match = setOf(2, 3).any(arr::contains)
特定のシナリオで範囲を使用することも可能です。
val match = (2..3).any(arr::contains)
最終的に、あなたのソリューションはすでに私にはかなり良さそうです。派手なライブラリ機能を使用していませんが。
別の便利な方法は、実際にはKotlinの方法ではなく、Java Collections。
それを知ることも良いことです。
Collections.disjoint(Collection<?> c1, Collection<?> c2)
指定された2つのコレクションに共通の要素がない場合、{@ code true}を返します。
@Test
fun disjointCollections() {
val list = listOf(1, 2, 3)
assertTrue(Collections.disjoint(list, listOf(7, 8)))
assertFalse(Collections.disjoint(list, listOf(1)))
}