I try to create a tree of files with indentation without displaying duplicate files. Currently I have done this:
val listOfDisplayPaths : List<String> = listOf(
"/home/josh/project/app/src/index.js",
"/home/josh/project/app/images/logo.png",
"/home/peter/.bashrc",
"/var/log",
"/usr/lib/node14",
"/opt/apache2",
"/etc/hosts"
)
fun displayPaths(paths: List<String>): String {
val sb = StringBuilder()
var pathIndented = ""
for (p in paths) {
val path = p.split("/")
for (file in path){
val index = path.indexOf(file)
val pathWithoutIndent = sb.append(file "\n")
val space = addSpace(index)
pathIndented = sb.append(String.format(space, pathWithoutIndent)).toString()
}
}
return pathIndented
}
fun addSpace(index: Int): String {
if (index == 0){
return "- "
}
val space = " "
return space.repeat(index)
}
fun main(vararg args: String) {
displayPaths(listOfDisplayPaths)
}
Current result:
- home
josh
project
app
src
index.js
- home
josh
project
app
images
logo.png
- home
peter
.bashrc
- var
log
- usr
lib
node14
- opt
apache2
- etc
hosts
Expected result:
- home
josh
project
app
src
index.js
images
logo.png
peter
bashrc
- var
log
- usr
lib
node14
- opt
apache2
- etc
hosts
How to not display duplicate file titles while keeping the current indentation ?
I also have this warning without using print:
solution.kt:88:17: warning: parameter 'args' is never used fun main(vararg args: String){
^
How can I solve it?
EDIT: I have replaced
fun main(vararg args: String) {
displayPaths(listOfDisplayPaths)
}
By:
fun main() {
displayPaths(listOfDisplayPaths)
}
To solve the warning
Thanks by advance
CodePudding user response:
This is a perfect application for Trie data structure. You just put all the paths into the prefix tree and then traverse the tree creating an appropriate path string.
UPD: You might want to store children as a hash map, instead of a list for better search performance.
import java.util.LinkedList
class Trie {
data class Node(val value: String, var isFile: Boolean = false, val children: MutableList<Node> = LinkedList<Node>()) {
fun traversePath(currString: StringBuilder, tabs: Int = 1): String {
if (tabs == 1) currString.append("- ")
else repeat(tabs) { currString.append(" ") }
currString.append("${this.value}")
currString.append("\n")
if (this.isFile) return currString.toString()
this.children.forEach { it.traversePath(currString, tabs 1) }
return currString.toString()
}
}
val root = Node("")
fun add(path: List<String>) {
if (path.isEmpty()) return
var currNode = root
for (name in path) {
var nextNode = currNode.children.firstOrNull { it.value == name }
if (nextNode == null) {
nextNode = Node(name)
currNode.children.add(nextNode)
}
currNode = nextNode
}
currNode.isFile = true
}
}
val listOfDisplayPaths : List<String> = listOf(
"/home/josh/project/app/src/index.js",
"/home/josh/project/app/images/logo.png",
"/home/peter/.bashrc",
"/var/log",
"/usr/lib/node14",
"/opt/apache2",
"/etc/hosts"
)
fun displayPaths(paths: List<String>): String {
val sb = StringBuilder()
val trie = Trie()
for (path in paths) trie.add(path.trim('/').split("/"))
for (node in trie.root.children) {
sb.append(node.traversePath(StringBuilder()))
sb.append('\n')
}
return sb.toString()
}
fun main() {
println(displayPaths(listOfDisplayPaths))
}