Reputation: 17470
Sorry for the poor title but it is rather hard to describe my use case in a short sentence.
I have the following model:
typealias Identifier = String
data class Data(val identifier: Identifier,
val data1: String,
val data2: String)
And I have three main data structures in my use case:
Set
of Identifier
s that exist and are valid in a given context. Example:val existentIdentifiers = setOf("A-1", "A-2", "B-1", "B-2", "C-1")
Map
that contains a List
of Data
objects per Identifier
. Example: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"))
)
List
of List
s that group together the Identifier
s that should share the same List<Data>
(each List
includes always 2 Identifier
s). Exampleval identifiersWithSameData = listOf(listOf("A-1", "A-2"), listOf("B-1", "B-2"))
The problem that I am trying to tackle stems from the fact that dataPerIdentifier
might not contain all identifiersWithSameData
given that existentIdentifiers
contains such missing Identifier
s. I need to add those missing Identifier
to dataPerIdentifier
, copying the List<Data>
already in there.
Given the data in the Context section:
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)]
The desired outcome is to update dataPerIdentifier
so that it includes:
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)]
The reason is that existentIdentifiers
contains A-2
that is missing in the initial dataPerIdentifier
Map
. B-2
is also missing in the initial dataPerIdentifier
Map
but existentIdentifiers
does not contain it, so it is ignored.
I have already a working code (handleDataForMultipleIdentifiers()
method is the one doing the heavy lifting), but it does not feel to be the cleanest or easiest to read:
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)
So my question is: how can I do this in a simpler way?
Upvotes: 2
Views: 88
Reputation: 28362
If identifiersWithSameData
always contains 2 identifiers per item then it should not really be a list of lists, but rather a list of pairs or dedicated data classes. And if you convert this data structure into a map like this:
val identifiersWithSameData = mapOf("A-1" to "A-2", "A-2" to "A-1", "B-1" to "B-2", "B-2" to "B-1")
The the whole solution is pretty simple:
existentIdentifiers.associateWith {
dataPerIdentifier[it] ?: dataPerIdentifier[identifiersWithSameData[it]!!]!!
}
I'm not sure about both !!
, for example I don't know if it is guaranteed that identifier existing in existentIdentifiers
exists in identifiersWithSameData
as well. You may need to tune this solution a little.
Upvotes: 1