[英]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.