Reputation: 815
I am trying to create a new list that combines the contents of one single-level list with the hierarchy of another nested list and link them by the IDs of objects in both lists. Note: the ID for the BChain object is stored within the ItemObj inside it.
I have three objects:
ItemObj(id: String, stored: DateTime)
BChain(item: ItemObj, List[BChain])
AChain(aid: String, List[AChain])
I have two lists:
val nestedList: List[AChain]
val singleLevelList: List[BChain]
I want the second list to have the hierarchy of the first, but still contain it's own elements. Therefore, BChain
should include the original ItemObj
and List[BChain]
properties (including all of ItemObj
's original property data - ID and DateTime) when it is put into the newly desired list output.
So Instead of (input):
val nestedList = List(
AChain("123", List(AChain("456", [])),
AChain("789", [])
)
val singleLevelList = List(
BChain(ItemObj("123", DateTime), []),
BChain(ItemObj("456", DateTime), []),
BChain(ItemObj("789", DateTime), []))
)
I would like the following output:
val combinedLists = List(
BChain(ItemObj("123", DateTime), List(BChain(ItemObj("456", DateTime), [])),
BChain(ItemObj("789", DateTime), [])
)
as the final list.
Note: There may be more items in the nested list than the single-level list, and if this is the case then the extra items should be ignored. Each of the items in the single-level list should correspond to one of the items in the nested list.
How can I accomplish this?
Any help would be appreciated.
Upvotes: 0
Views: 408
Reputation: 51271
First I had to dummy up a DateTime
type and value so that the following would compile.
case class ItemObj(id: String, stored: DateTime)
case class BChain(item: ItemObj, bcl :List[BChain])
case class AChain(aid: String, acl :List[AChain])
Then I changed your singleLevelList
into real Scala code and created a Map
for fast lookup.
val singleLevelList = List(
BChain(ItemObj("123", DateTime), Nil),
BChain(ItemObj("456", DateTime), Nil),
BChain(ItemObj("789", DateTime), Nil)
)
val sLLMap = singleLevelList.groupBy(_.item.id)
Next a recursive method to change all AChain
s to BChain
s.
def a2b(aLst :List[AChain]) :List[BChain] =
aLst.map(a => BChain(sLLMap(a.aid).head.item, a2b(a.acl)))
Now to test it.
val nestedList = List(
AChain("123", List(AChain("456", Nil))),
AChain("789", Nil)
)
a2b(nestedList) //appears to work
Of course this will throw if nestedList
has an A without a corresponding B in the singleLevelList
.
Upvotes: 1
Reputation: 3032
This code will work even if root element of nested list is absent in single level list
final case class ItemObj(id: String, stored: DateTime = null)
final case class AChain(aid: String, children: List[AChain] = List())
final case class BChain(bid: ItemObj, children: List[BChain] = List())
val nestedList = List(
AChain("123", List(AChain("456"))),
AChain("789")
)
def getCombineList(nestedList: List[AChain], singleList: List[BChain]): List[BChain] = {
val singleListMap = singleList.groupBy(_.bid.id)
def combine(items: List[AChain]): List[BChain] = {
items flatMap {item =>
val children = combine(item.children)
val parent = singleListMap.get(item.aid).map(v =>
List(v.head.copy(children = children))
).getOrElse(
children
)
parent
}
}
combine(nestedList)
}
val s = getCombineList(nestedList, List(BChain(ItemObj("456")), BChain(ItemObj("789"))))
Upvotes: 1
Reputation: 22850
Maybe something like this is what you want?
final case class ItemObj(id: String, stored: DateTime)
final case class BChain(item: ItemObj, list: List[BChain])
final case class AChain(aid: String, list: List[AChain])
def combine(as: List[AChain], bs: List[BChain]): List[BChain] = {
val asMap = as.iterator.map(a => a.aid -> a.list).toMap
def toBChain(a: AChain): BChain =
BChain(
item = ItemObj(id = a.aid, stored = ???),
list = a.list.map(toBChain)
)
bs.map {
case BChain(item, list) =>
val newElements =
asMap
.getOrElse(key = item.id, default = Nil)
.map(toBChain)
BChain(
item,
list ::: newElements
)
}
}
Upvotes: 1