【问题标题】:How to add data to Map copying existing values based on List of identifiers如何根据标识符列表将数据添加到地图复制现有值
【发布时间】:2022-01-18 05:04:07
【问题描述】:

很抱歉标题不好,但很难用一句话来描述我的用例。

上下文

我有以下型号:

typealias Identifier = String

data class Data(val identifier: Identifier,
                val data1: String,
                val data2: String)

我的用例中有三个主要的数据结构:

  • Set 中的 Identifiers 存在且在给定上下文中有效。示例:
val existentIdentifiers = setOf("A-1", "A-2", "B-1", "B-2", "C-1")
  • 一个Map,每个Identifier 包含ListData 对象。示例:
val dataPerIdentifier: Map<Identifier, List<Data>> = mapOf(
    "A-1" to listOf(Data("A-1", "Data-1-A", "Data-2-A"), Data("A-1", "Data-1-A", "Data-2-A")),
    "B-1" to listOf(Data("B-1", "Data-1-B", "Data-2-B")),
    "C-1" to listOf(Data("C-1", "Data-1-C", "Data-2-C"))
)
  • ListLists 将应共享相同 List&lt;Data&gt;Identifiers 组合在一起(每个 List 始终包含 2 个 Identifiers)。示例
val identifiersWithSameData = listOf(listOf("A-1", "A-2"), listOf("B-1", "B-2"))

问题/用例

我试图解决的问题源于dataPerIdentifier 可能不包含所有identifiersWithSameData,因为existentIdentifiers 包含这样的缺失Identifiers。我需要将那些缺少的Identifier 添加到dataPerIdentifier,复制那里已经存在的List&lt;Data&gt;

示例

鉴于上下文部分中的数据:

A-1=[Data(identifier=A-1, data1=Data-1-A, data2=Data-2-A), 
     Data(identifier=A-1, data1=Data-1-A, data2=Data-2-A)], 
B-1=[Data(identifier=B-1, data1=Data-1-B, data2=Data-2-B)], 
C-1=[Data(identifier=C-1, data1=Data-1-C, data2=Data-2-C)]

期望的结果是更新dataPerIdentifier,使其包括:

A-1=[Data(identifier=A-1, data1=Data-1-A, data2=Data-2-A), 
     Data(identifier=A-1, data1=Data-1-A, data2=Data-2-A)], 
B-1=[Data(identifier=B-1, data1=Data-1-B, data2=Data-2-B)], 
C-1=[Data(identifier=C-1, data1=Data-1-C, data2=Data-2-C)], 
A-2=[Data(identifier=A-2, data1=Data-1-A, data2=Data-2-A), 
     Data(identifier=A-2, data1=Data-1-A, data2=Data-2-A)]

原因是existentIdentifiers 包含A-2,而初始dataPerIdentifier Map 中缺少该A-2B-2 在最初的dataPerIdentifier Map 中也缺少,但existentIdentifiers 不包含它,因此被忽略。

可能的解决方案

我已经有一个工作代码(handleDataForMultipleIdentifiers() 方法是最繁重的方法),但感觉不是最干净或最容易阅读的代码:

fun main(args: Array<String>) {
    val existentIdentifiers = setOf("A-1", "A-2", "B-1", "C-1")

    val dataPerIdentifier: Map<Identifier, List<Data>> = mapOf(
        "A-1" to listOf(Data("A-1", "Data-1-A", "Data-2-A"), Data("A-1", "Data-1-A", "Data-2-A")),
        "B-1" to listOf(Data("B-1", "Data-1-B", "Data-2-B")),
        "C-1" to listOf(Data("C-1", "Data-1-C", "Data-2-C"))
    )

    val identifiersWithSameData = listOf(listOf("A-1", "A-2"), listOf("B-1", "B-2"))

    print("Original Data")
    println(dataPerIdentifier)

    print("Target Data")
    println(dataPerIdentifier.handleDataForMultipleIdentifiers(identifiersWithSameData, existentIdentifiers))
}

fun Map<Identifier, List<Data>>.handleDataForMultipleIdentifiers(identifiersWithSameData: List<List<Identifier>>, existentIdentifiers: Set<Identifier>)
        : Map<Identifier, List<Data>> {
    val additionalDataPerIdentifier = identifiersWithSameData
        .mapNotNull { identifiersList ->
            val identifiersWithData = identifiersList.find { it in this.keys }
            identifiersWithData?.let { it to identifiersList.minus(it).filter { it in existentIdentifiers } }
        }.flatMap { (existentIdentifier, additionalIdentifiers) ->
            val existentIdentifierData = this[existentIdentifier].orEmpty()
            additionalIdentifiers.associateWith { identifier -> existentIdentifierData.map { it.copy(identifier = identifier) } }.entries
        }.associate { it.key to it.value }

    return this + additionalDataPerIdentifier
}

typealias Identifier = String

data class Data(val identifier: Identifier,
                val data1: String,
                val data2: String)

所以我的问题是:我怎样才能以更简单的方式做到这一点?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    如果identifiersWithSameData 每个项目总是包含 2 个标识符,那么它不应该是一个真正的列表列表,而是一个对或专用数据类的列表。如果你把这个数据结构转换成这样的地图:

    val identifiersWithSameData = mapOf("A-1" to "A-2", "A-2" to "A-1", "B-1" to "B-2", "B-2" to "B-1")
    

    整个解决方案非常简单:

    existentIdentifiers.associateWith {
        dataPerIdentifier[it] ?: dataPerIdentifier[identifiersWithSameData[it]!!]!!
    }
    

    我不确定!!,例如我不知道是否可以保证existentIdentifiers 中存在的标识符也存在于identifiersWithSameData 中。您可能需要稍微调整一下这个解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2016-11-29
      • 2011-09-19
      • 1970-01-01
      相关资源
      最近更新 更多