簡體   English   中英

Kotlin - 合並兩個數據 class

[英]Kotlin - Merge two data class

數據 class

data class A(
    var data: List<Data>
) {
    data class Data(
        var key: String,
        var count: Long = 0,
        var sub: List<Data>? = null
    )
}

A class 數據值以 json 表示。

[
  {
    "data": [
      {
        "key": "ALLOGENE THERAPEUTICS",
        "count": 47,
        "sub": [
          {
            "key": "N",
            "count": 46,
            "sub": [
              {
                "key": "S1",
                "count": 1
              },
              {
                "key": "S2",
                "count": 13
              }
            ]
          },
          {
            "key": "B+",
            "count": 1,
            "sub": [
              {
                "key": "S1",
                "count": 2
              },
              {
                "key": "S2",
                "count": 1
              }
            ]
          }
        ]
      },
      {
        "key": "CELLECTIS",
        "count": 5,
        "sub": [
          {
            "key": "B+",
            "count": 2,
            "sub": [
              {
                "key": "S1",
                "count": 3
              },
              {
                "key": "S2",
                "count": 5
              }
            ]
          },
          {
            "key": "B",
            "count": 2,
            "sub": [
              {
                "key": "S1",
                "count": 6
              },
              {
                "key": "S2",
                "count": 1
              }
            ]
          },
          {
            "key": "N",
            "count": 1,
            "sub": [
              {
                "key": "S1",
                "count": 8
              },
              {
                "key": "S2",
                "count": 4
              }
            ]
          }
        ]
      },
      {
        "key": "PFIZER",
        "count": 5,
        "sub": [
          {
            "key": "N",
            "count": 5,
            "sub": [
              {
                "key": "S1",
                "count": 83
              },
              {
                "key": "S2",
                "count": 1
              }
            ]
          }
        ]
      }
    ]
  }
]

我想將元素與“ALLOGENE THERAPEUTICS”和“CELECTIS”的關鍵值結合起來,並用“STUB”替換關鍵值。

組合元素時,必須組合所有“計數”值。

並且必須添加不存在的元素。

因此,結果應如下所示。

[
  {
    "data": [
      {
        "key": "STUB",
        "count": 52, // "ALLOGENE THERAPEUTICS"(47) + "CELECTIS"(5) = 52
        "sub": [
          {
            "key": "N", 
            "count": 47,  // 46 + 1
            "sub": [
              {
                "key": "S1",
                "count": 9
              },
              {
                "key": "S2",
                "count": 17
              }
            ]
          },
          {
            "key": "B+",
            "count": 3,
            "sub": [
              {
                "key": "S1",
                "count": 5
              },
              {
                "key": "S2",
                "count": 6
              }
            ]
          },
          {
            "key": "B",
            "count": 5,
            "sub": [
              {
                "key": "S1",
                "count": 11
              },
              {
                "key": "S2",
                "count": 7
              }
            ]
          }
        ]
      },
      {
        "key": "PFIZER",
        "count": 5,
        "sub": [
          {
            "key": "N",
            "count": 5,
            "sub": [
              {
                "key": "S1",
                "count": 83
              },
              {
                "key": "S2",
                "count": 1
              }
            ]
          }
        ]
      }
    ]
  }
]

如何使用 Kotlin 巧妙地編碼工作?

作為參考,數據 class 的值表示為 json,結果值必須是數據 class。

這是迄今為止的進展:

為創建合並副本的數據創建 function

data class Data(
    var key: String,
    var count: Long = 0,
    var sub: List<Data> = emptyList()
) {
    fun mergedWith(other: Data): Data {
        return copy(
            count = count + other.count,
            sub = sub + other.sub
        )
    }
}

將合並列表折疊成單個數據項並將它們重新添加到一起。

val consolidatedKeys = listOf("ALLOGENE THERAPEUTICS", "CELECTIS")
val (consolidatedValues, nonconsolidatedValues) = a.data.partition { it.key in consolidatedKeys }
val consolidatedData = when {
    consolidatedValues.isEmpty() -> emptyList()
    else -> listOf(consolidatedValues.fold(A.Data("STUB", 0), A.Data::mergedWith))
}
val result = A(consolidatedData + nonconsolidatedValues)

並結合子元素。

consolidatedData.forEach { x ->
            x.sub
                .groupBy { group -> group.key }
                .map { A.Data(it.key, it.value.sumOf { c -> c.count }) }
}

這是目前的情況。

這樣,深度為2的元素會正常工作,但深度為3的元素不會被添加。

例如,STUB 下最多“N”被組合,但“N”下的“S1”和“S2”不被組合。

因此,這種方式當前的結果是output。

[
  {
    "data": [
      {
        "key": "STUB",
        "count": 52, <--------- WORK FINE
        "sub": [
          {
            "key": "N", 
            "count": 47, <--------- WORK FINE
            "sub": [] <--------- EMPTY !!
          },
          {
            "key": "B+",
            "count": 3, <--------- WORK FINE
            "sub": [] <--------- EMPTY !!
          },
          {
            "key": "B",
            "count": 5, <--------- WORK FINE
            "sub": [] <--------- EMPTY !!
          }
        ]
      },
      {
        "key": "PFIZER",
        "count": 5,
        "sub": [
          {
            "key": "N",
            "count": 5,
            "sub": [
              {
                "key": "S1",
                "count": 83
              },
              {
                "key": "S2",
                "count": 1
              }
            ]
          }
        ]
      }
    ]
  }
]

所有的子元素如何組合和實現?

首先分解你的問題。 您可以為創建合並副本的數據創建 function:

fun mergedWith(other: Data): Data {
    return copy(
        count = count + other.count,
        sub = when {
            sub == null && other.sub == null -> null
            else -> sub.orEmpty() + other.sub.orEmpty()
        }
    )
}

如果可能,我建議您為sub參數使用不可為空的 List,並在其中沒有任何內容時使用emptyList() 這使得它更簡單,因為沒有兩種不同的方式來表示缺少項目,並且您不必處理可空性:

data class Data(
    var key: String,
    var count: Long = 0,
    var sub: List<Data> = emptyList()
) {
    fun mergedWith(other: Data): Data {
        return copy(
            count = count + other.count,
            sub = sub + other.sub
        )
    }
}

然后,您可以將列表拆分為您想要合並的列表與 rest。 然后將合並列表折疊成單個數據項並將它們重新添加在一起。

val consolidatedKeys = listOf("ALLOGENE THERAPEUTICS", "CELECTIS")
val (consolidatedValues, nonconsolidatedValues) = a.data.partition { it.key in consolidatedKeys }
val consolidatedData = when {
    consolidatedValues.isEmpty() -> emptyList()
    else -> listOf(consolidatedValues.fold(A.Data("STUB", 0), A.Data::mergedWith))
}
val result = A(consolidatedData + nonconsolidatedValues)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM