Skip to content

Instantly share code, notes, and snippets.

@Kyome22
Created August 9, 2022 14:28
Show Gist options
  • Save Kyome22/7d1dd240fe0505a4521dd398116a0b20 to your computer and use it in GitHub Desktop.
Save Kyome22/7d1dd240fe0505a4521dd398116a0b20 to your computer and use it in GitHub Desktop.
Print an object like the tree format.
import Foundation
struct SwiftTree {
enum RuledLine {
static let root = "."
static let stem = "│  "
static let branch = "├──"
static let lastBranch = "└──"
static let space = "   "
}
enum Parent {
case none
case array
case dictionary
}
static func print(_ obj: Any?) {
let output = SwiftTree.makeTree(obj: obj).joined(separator: "\n")
Swift.print(output)
}
private static func makeTree(obj: Any?, parent: Parent = .none, isLast: Bool = false, prefix: [String] = []) -> [String] {
var result = [String]()
if let dict = obj as? [String: Any?] { // Dictionay
let array: [(key: String, value: Any?)] = dict.sorted { $0.key < $1.key }
if parent == .array, array.count == 1, let first = array.first {
result.append(contentsOf: makeTree(obj: first.key,
parent: .array,
isLast: isLast,
prefix: prefix))
let valuePrefix = prefix + [isLast ? RuledLine.space : RuledLine.stem]
result.append(contentsOf: makeTree(obj: first.value,
parent: .dictionary,
isLast: true,
prefix: valuePrefix))
} else {
if parent == .none {
result.append(RuledLine.root)
} else if parent == .array {
result.append(contentsOf: makeTree(obj: RuledLine.root,
parent: .array,
isLast: isLast,
prefix: prefix))
}
for i in (0 ..< array.count) {
let isLastValue: Bool = (i == array.count - 1)
var keyPrefix = prefix
if parent == .array {
keyPrefix.append(isLast ? RuledLine.space : RuledLine.stem)
}
result.append(contentsOf: makeTree(obj: array[i].key,
parent: .dictionary,
isLast: isLastValue,
prefix: keyPrefix))
let valuePrefix = keyPrefix + [isLastValue ? RuledLine.space : RuledLine.stem]
result.append(contentsOf: makeTree(obj: array[i].value,
parent: .dictionary,
isLast: true,
prefix: valuePrefix))
}
}
} else if let array = obj as? [Any?] { // Array
if array.isEmpty {
let isLastValue: Bool = (parent == .dictionary ? true : isLast)
result.append(contentsOf: makeTree(obj: "empty",
parent: .array,
isLast: isLastValue,
prefix: prefix))
} else if parent == .array, array.count == 1, let first = array.first {
result.append(contentsOf: makeTree(obj: first,
parent: .array,
isLast: isLast,
prefix: prefix))
} else {
if parent == .none {
result.append(RuledLine.root)
} else if parent == .array {
result.append(contentsOf: makeTree(obj: RuledLine.root,
parent: .array,
isLast: isLast,
prefix: prefix))
}
for i in (0 ..< array.count) {
let isLastValue: Bool = i == (array.count - 1)
var valuePrefix = prefix
if parent == .array {
valuePrefix.append(isLast ? RuledLine.space : RuledLine.stem)
}
result.append(contentsOf: makeTree(obj: array[i],
parent: .array,
isLast: isLastValue,
prefix: valuePrefix))
}
}
} else { // Element
let valuePrefix = prefix + [isLast ? RuledLine.lastBranch : RuledLine.branch]
let line = (valuePrefix + ["\(obj ?? "nil")"]).joined(separator: " ")
result.append(line)
}
return result
}
}
@Kyome22
Copy link
Author

Kyome22 commented Aug 9, 2022

How to use

Print Sample Object

let dict: [String: Any?] = [
    "Drink": [
        "RedBull",
        "Monster",
        "RealGold",
    ],
    "Price": [
        108,
        216,
        300.33
    ],
    "Food": [
        "Sushi": [
            "Maguro",
            "Sake",
            "Ikura",
            "Uni",
        ],
        "Yakiniku": [
            "Harami",
            "Karubi",
            nil
        ],
    ],
    "Piyo": [
        [
            "Meu": 1,
            "Foo": 2,
            "Gao": 3
        ],
        [
            "Jake": 4,
            "Gomi": 5
        ]
    ],
    "Hoge": nil
]

SwiftTree.print(dict)

Output

.
├── Drink
   ├── RedBull
   ├── Monster
   └── RealGold
├── Food
   ├── Sushi
      ├── Maguro
      ├── Sake
      ├── Ikura
      └── Uni
   └── Yakiniku
       ├── Harami
       ├── Karubi
       └── nil
├── Hoge
   └── nil
├── Piyo
   ├── .
      ├── Foo
         └── 2
      ├── Gao
         └── 3
      └── Meu
          └── 1
   └── .
       ├── Gomi
          └── 5
       └── Jake
           └── 4
└── Price
    ├── 108.0
    ├── 216.0
    └── 300.33

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment