I have a list of objects, which contain a list of objects of a same type. E.g.
List[CustomObject(objName, List[CustomObject])]
Currently, I have a program that combines these CustomObjects into a single list. However, they contain all possible "list paths". I want to be able to remove certain paths if they've already been referenced in a longer path.
List(CustomObject("obj-1", List(CustomObject("obj-2", List(CustomObject("obj-3", List())))))
The program outputs all possible paths. For example, it will output in the same list
[obj-1 -> obj-2 ->obj-3,
obj-1 -> obj-2]
I want to be able to remove the obj-1 -> obj2 because the path is already shown. But I would like to keep that path if further down the path contains different children. For example, the following is desired output where I would rather keep the path. Basically, I want the paths to be unique
[obj-1 -> obj-2-A -> obj -3,
obj-1 -> obj-2-B -> obj-4]
Requirement: all of the objects will be nested within a single list, not seperate lists.
This has been difficult to explain, so I apologise if it's hard to understand.
EDIT: I'm currently removing any sub-items which are not the longest. However, I do not retain the desired output, because I don't know how to check if a path is totally unique from start to end. If it's not unique from start to end and the entire path is a sub-path of another path, then I want to remove it.
Assuming paths are represented as tuples
val l1 = List(
("obj-1", "obj-2", "obj-3"),
("obj-1", "obj-2")
)
val l2 = List(
("obj-1", "obj-2", "obj-3"),
("obj-1", "obj-2", "obj-4")
)
here is my attempt which depends on finding all indices of startsWith predicate
def removeDuplicateSubpaths(paths: List[Product]): List[Product] = {
val l = fromTuple(paths)
l.map { path =>
l
.zipWithIndex
.filter(_._1.startsWith(path))
.map(_._2)
}
.zip(l)
.filter(_._1.size == 1)
.map(_._2)
.map(toTuple)
}
which outputs
removeDuplicateSubpaths(l1) // List((obj-1,obj-2,obj-3))
removeDuplicateSubpaths(l2) // List((obj-1,obj-2,obj-3), (obj-1,obj-2,obj-4))
I reconstitute from and to tuples without knowing arity like so
def fromTuple[T](paths: List[Product]): List[List[T]] =
paths.map(_.productIterator.toList.asInstanceOf[List[T]])
def toTuple[A](as: List[A]): Product = {
val tupleClass = Class.forName("scala.Tuple" + as.size)
tupleClass.getConstructors.apply(0).newInstance(as:_*).asInstanceOf[Product]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With