1

数据类

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

以 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 巧妙地编写代码?

作为参考,数据类的值用json表示,结果值必须是数据类。

这是迄今为止的进展:

为创建合并副本的数据创建一个函数

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”不被组合。

因此,以这种方式输出当前结果。

[
  {
    "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
              }
            ]
          }
        ]
      }
    ]
  }
]

所有的子元素如何组合和实现?

4

1 回答 1

1

首先分解你的问题。您可以为创建合并副本的 Data 创建一个函数:

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参数使用不可为空的列表,并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
        )
    }
}

然后,您可以将列表拆分为您想要合并的列表与其他列表。然后将合并列表折叠成单个数据项并将它们重新添加在一起。

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)
于 2022-01-12T16:42:33.823 回答