Kotlinでリストをパーツに分割する

1. 前書き

_ [a、b、c、d、e、f] _のような配列があり、_ [[a、b]、[c、d]、[のような要素を別々のグループに分割したいとしますe、f]] _または_ [[a、b、c]、[d]、[e、f]] _。
*このチュートリアルでは、Kotlinの_groupBy、chunked、_、および_windowed_の違いを調べながらこれを実現します。*

2. リストをペアのリストに分割する

この例では、2つのリストを使用します。1つは要素数が偶数で、もう1つは要素数が奇数です。
val evenList = listOf(0, "a", 1, "b", 2, "c");
val unevenList = listOf(0, "a", 1, "b", 2, "c", 3);
明らかに、_evenList_を正確に3つのペアに分割できます。 ただし、_unevenList_には余​​分な要素が1つあります。
このセクションの残りの部分では、_unevenList_内の余分な要素をどのように扱うかなど、2つのリストを分割するためのさまざまな実装について説明します。

* 2.1。 groupBy *の使用

まず、g__roupBy__を使用してソリューションを実装しましょう。 *昇順の番号のリストを作成し、_groupBy_を使用してそれらを分割します:*
val numberList = listOf(1, 2, 3, 4, 5, 6);
numberList.groupBy { (it + 1) / 2 }.values
これにより、望ましい結果が得られます。
[[1, 2], [3, 4], [5, 6]]
それはどのように機能しますか? _groupBy_は、提供された関数_(it + 1)/ 2_をすべての要素で実行します:
  • (1 + 1)/ 2 = 1

  • (2 + 1)/ 2 = 1.5、1に丸められます

  • (3 + 1)/ 2 = 2

  • (4 + 1)/ 2 = 2.5、2に丸められます

  • (5 + 1)/ 2 = 3

  • (6 + 1)/ 2 = 3.5、3に丸められます

    次に、グループ化は、同じ結果を持つリスト内の要素をグループ化します。
    今、不均一なリストで同じことをするとき:
val numberList = listOf(1, 2, 3, 4, 5, 6, 7);
numberList.groupBy { (it + 1) / 2 }.values
すべてのペアと1つの追加要素を取得します。
[[1, 2], [3, 4], [5, 6], [7]]
しかし、*いくつかの乱数でさらに進んだ場合:*
val numberList = listOf(1, 3, 8, 20, 23, 30);
numberList.groupBy { (it + 1) / 2 }.values
*私たちは完全に望ましくないものを手に入れます:*
[[1], [3], [8], [20], [23], [30]]
その理由は簡単です。すべての要素に_(it + 1)/ 2_関数を適用すると、_1、2、4、10、12、15_が得られます。 結果はすべて異なるため、要素はグループ化されません。
_evenList_または_unevenList_を使用すると、さらに悪化します。関数は_Strings_に適用できないため、*コードはコンパイルされません*。

* 2.2。 groupBy_および_withIndex *の使用

実際、任意のリストをペアにグループ化する場合、*関数で__value __を変更するのではなく、_index _:*
evenList.withIndex()
    .groupBy { it.index / 2 }
    .map { it.value.map { it.value } }
これにより、必要なペアのリストが返されます。
[[0, "a"], [1, "b"], [2, "c"]]
さらに、_unevenList_を使用すると、別の要素も取得できます。
[[0, "a"], [1, "b"], [2, "c"], [3]]

* 2.3。 foldByed *で_groupBy_を使用する

_index_を使用するだけでなく、_foldIndexed_でもう少しプログラムして割り当てを保存することもできます。
evenList.foldIndexed(ArrayList<ArrayList<Any>>(evenList.size / 2)) { index, acc, item ->
    if (index % 2 == 0) {
        acc.add(ArrayList(2))
    }
    acc.last().add(item)
    acc
}
もう少し冗長ですが、_foldIndexed_ソリューションは単純に各要素に対して操作を実行しますが、_withIndex_関数は最初に反復子を作成して各要素をラップします。

* 2.4。 chunked *の使用

*しかし、これを_chunked_でよりエレガントに行うことができます。*メソッドを_evenList_に適用しましょう:
evenList.chunked(2)
_evenList_は、必要なペアを提供します。
[[0, "a"], [1, "b"], [2, "c"]]
_unevenList_はペアと追加要素を提供します:
[[0, "a"], [1, "b"], [2, "c"], [3]]

* 2.5。 windowed *の使用

*また、_chunked_は非常にうまく機能しますが、もう少し制御が必要な場合があります。*
たとえば、ペアのみが必要な場合、または追加要素を含めるかどうかを指定する必要がある場合があります。 * _windowed_メソッドは、_partialWindows_ブール値*を提供します。これは、部分的な結果が必要かどうかを示します。
デフォルトでは、_partialWindows_は_false_です。 したがって、次のステートメントは同じ結果を生成します。
evenList.windowed(2, 2)
unevenList.windowed(2, 2, false)
両方とも、個別の要素なしでリストを返します。
[[0, "a"], [1, "b"], [2, "c"]]
最後に、_partialWindows_を_true_に設定して、部分的な結果を含めます。
unevenList.windowed(2, 2, true)
ペアのリストと個別の要素を取得します。
[[0, "a"], [1, "b"], [2, "c"], [3]]

3. 結論

_groupBy_を使用することは、優れたプログラミング演習ですが、エラーが発生しやすくなります。 一部のエラーは、_index_を使用するだけで解決できます。
コードを最適化するために、_foldIndexed_を使用することもできます。 ただし、これによりさらに多くのコードが生成されます。 幸いなことに、_chunked_メソッドは、すぐに使用できる同じ機能を提供します。
さらに、_windowed_メソッドは追加の構成オプションを提供します。 *可能であれば、_chunked_メソッドを使用するのが最善です。追加の設定が必要な場合は、_windowed_メソッドを使用する必要があります。*
通常どおり、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-kotlin-2[GitHub]で入手できます。