Skip to content

Commit fcfd77c

Browse files
add MutableList<T>.mapToHierarchy()
1 parent 3d00298 commit fcfd77c

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

src/main/kotlin/KotlinFunctionLibrary.kt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,62 @@ println("workingList2=$workingList2")*/
11211121
}
11221122
return destination
11231123
}
1124+
1125+
data class HierarchicalNode<T>(
1126+
val data: T,
1127+
val hierarchyLevel: Int,
1128+
var parent: HierarchicalNode<T>? = null
1129+
)
1130+
/**
1131+
* Given a list of a hierarchical type [T], such that one [T] can be defined as the parent of another (potentially nested arbitrarily),
1132+
* return a list of [HierarchicalNode]s classifying the given [T]s as children and parents.
1133+
* For example, given a list of tasks, subtasks, sub-subtasks, etc., by defining a way to identify the level of
1134+
* hierarchy of a particular [T], this function can return a list of [HierarchicalNode]s representing that hierarchy.
1135+
* In this case, and example call could be:
1136+
* mutableListOf("-A","--1","--2","-B").mapToHierarchy({ it.count { it == '-' } }) { it.removePrefix("-") }
1137+
* */
1138+
fun <T, R> MutableList<T>.mapToHierarchy(
1139+
getHierarchicalLevel: (T) -> Int,
1140+
transform: (T) -> R,
1141+
): List<HierarchicalNode<R>> {
1142+
val nodes = mutableListOf<HierarchicalNode<R>>()
1143+
while (isNotEmpty()) {
1144+
val thisElement = removeFirst()
1145+
val thisLevel = getHierarchicalLevel(thisElement)
1146+
1147+
val nextElement = firstOrNull()
1148+
val nextLevel = nextElement?.let(getHierarchicalLevel)
1149+
1150+
val parent = nodes.findLast { it.hierarchyLevel < thisLevel }
1151+
val thisNode = HierarchicalNode(transform(thisElement), thisLevel, parent)
1152+
if (parent == null) nodes.add(thisNode) //add root
1153+
if (nextLevel != null) {
1154+
when {
1155+
thisLevel < nextLevel -> nodes.add(
1156+
HierarchicalNode(
1157+
transform(nextElement),
1158+
nextLevel,
1159+
thisNode
1160+
)
1161+
) //moving up levels of hierarchy, add next with parent as this
1162+
thisLevel > nextLevel -> nodes.add(
1163+
HierarchicalNode(
1164+
transform(nextElement),
1165+
nextLevel,
1166+
nodes.findLast { it.hierarchyLevel < nextLevel })
1167+
) //moving down levels of hierarchy, find previous parent
1168+
else /*equal*/ -> nodes.add(
1169+
HierarchicalNode(
1170+
transform(nextElement),
1171+
nextLevel,
1172+
thisNode.parent
1173+
)
1174+
) //same parent/level of hierarchy
1175+
}
1176+
}
1177+
}
1178+
return nodes.toList()
1179+
}
11241180

11251181
/**
11261182
* A `val foo by lazy {}` alternative that supports vars, viz. `var foo = by LazyMutable {}`

0 commit comments

Comments
 (0)