title: Kotlin - Merge two data class
body: <p><strong>Data class</strong></p>
  <pre><code>data class A(
      var data: List&lt;Data&gt;
  ) {
      data class Data(
          var key: String,
          var count: Long = 0,
          var sub: List&lt;Data&gt;? = null
      )
  }
  </code></pre>
  <p><strong>A class data values expressed in json.</strong></p>
  <pre><code>[
    {
      &quot;data&quot;: [
        {
          &quot;key&quot;: &quot;ALLOGENE THERAPEUTICS&quot;,
          &quot;count&quot;: 47,
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;,
              &quot;count&quot;: 46,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 1
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 13
                }
              ]
            },
            {
              &quot;key&quot;: &quot;B+&quot;,
              &quot;count&quot;: 1,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 2
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 1
                }
              ]
            }
          ]
        },
        {
          &quot;key&quot;: &quot;CELLECTIS&quot;,
          &quot;count&quot;: 5,
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;B+&quot;,
              &quot;count&quot;: 2,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 3
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 5
                }
              ]
            },
            {
              &quot;key&quot;: &quot;B&quot;,
              &quot;count&quot;: 2,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 6
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 1
                }
              ]
            },
            {
              &quot;key&quot;: &quot;N&quot;,
              &quot;count&quot;: 1,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 8
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 4
                }
              ]
            }
          ]
        },
        {
          &quot;key&quot;: &quot;PFIZER&quot;,
          &quot;count&quot;: 5,
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;,
              &quot;count&quot;: 5,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 83
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
  </code></pre>
  <p>I would like to combine elements with key values of &quot;ALLOGENE THERAPEUTICS&quot; and &quot;CELECTIS&quot; and replace the key value with &quot;STUB&quot;.</p>
  <p>When the elements are combined, all the &quot;count&quot; values must be combined.</p>
  <p>And elements that are not there must be added.</p>
  <p>Therefore, the results should be as follows.</p>
  <pre><code>[
    {
      &quot;data&quot;: [
        {
          &quot;key&quot;: &quot;STUB&quot;,
          &quot;count&quot;: 52, // &quot;ALLOGENE THERAPEUTICS&quot;(47) + &quot;CELECTIS&quot;(5) = 52
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;, 
              &quot;count&quot;: 47,  // 46 + 1
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 9
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 17
                }
              ]
            },
            {
              &quot;key&quot;: &quot;B+&quot;,
              &quot;count&quot;: 3,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 5
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 6
                }
              ]
            },
            {
              &quot;key&quot;: &quot;B&quot;,
              &quot;count&quot;: 5,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 11
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 7
                }
              ]
            }
          ]
        },
        {
          &quot;key&quot;: &quot;PFIZER&quot;,
          &quot;count&quot;: 5,
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;,
              &quot;count&quot;: 5,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 83
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
  </code></pre>
  <p>How can I code the work neatly with Kotlin?</p>
  <p>For reference, the values of the data class are expressed as json, and the result value must be data class.</p>
  <p><strong>This is the progress so far:</strong></p>
  <p>create a function for Data that creates a merged copy</p>
  <pre><code>data class Data(
      var key: String,
      var count: Long = 0,
      var sub: List&lt;Data&gt; = emptyList()
  ) {
      fun mergedWith(other: Data): Data {
          return copy(
              count = count + other.count,
              sub = sub + other.sub
          )
      }
  }
  </code></pre>
  <p>fold the consolidation list into a single data item and add them back together.</p>
  <pre><code>val consolidatedKeys = listOf(&quot;ALLOGENE THERAPEUTICS&quot;, &quot;CELECTIS&quot;)
  val (consolidatedValues, nonconsolidatedValues) = a.data.partition { it.key in consolidatedKeys }
  val consolidatedData = when {
      consolidatedValues.isEmpty() -&gt; emptyList()
      else -&gt; listOf(consolidatedValues.fold(A.Data(&quot;STUB&quot;, 0), A.Data::mergedWith))
  }
  val result = A(consolidatedData + nonconsolidatedValues)
  </code></pre>
  <p>And combine the sub-elements.</p>
  <pre><code>consolidatedData.forEach { x -&gt;
              x.sub
                  .groupBy { group -&gt; group.key }
                  .map { A.Data(it.key, it.value.sumOf { c -&gt; c.count }) }
  }
  </code></pre>
  <p>This is the current situation.</p>
  <p>In this way, elements with depth of 2 will work normally, but elements with depth of 3 will not be added.</p>
  <p>For example, up to &quot;N&quot; below STUB is combined, but &quot;S1&quot; and &quot;S2&quot; below &quot;N&quot; are not combined.</p>
  <p>Therefore, the current result is output in this way.</p>
  <pre><code>[
    {
      &quot;data&quot;: [
        {
          &quot;key&quot;: &quot;STUB&quot;,
          &quot;count&quot;: 52, &lt;--------- WORK FINE
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;, 
              &quot;count&quot;: 47, &lt;--------- WORK FINE
              &quot;sub&quot;: [] &lt;--------- EMPTY !!
            },
            {
              &quot;key&quot;: &quot;B+&quot;,
              &quot;count&quot;: 3, &lt;--------- WORK FINE
              &quot;sub&quot;: [] &lt;--------- EMPTY !!
            },
            {
              &quot;key&quot;: &quot;B&quot;,
              &quot;count&quot;: 5, &lt;--------- WORK FINE
              &quot;sub&quot;: [] &lt;--------- EMPTY !!
            }
          ]
        },
        {
          &quot;key&quot;: &quot;PFIZER&quot;,
          &quot;count&quot;: 5,
          &quot;sub&quot;: [
            {
              &quot;key&quot;: &quot;N&quot;,
              &quot;count&quot;: 5,
              &quot;sub&quot;: [
                {
                  &quot;key&quot;: &quot;S1&quot;,
                  &quot;count&quot;: 83
                },
                {
                  &quot;key&quot;: &quot;S2&quot;,
                  &quot;count&quot;: 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
  </code></pre>
  <p>How can all the sub-elements be combined and implemented?</p>