Skip to content

Commit

Permalink
getChildren methods consolidated for consistency
Browse files Browse the repository at this point in the history
  • Loading branch information
Reed Es committed Nov 20, 2021
1 parent e767cd7 commit 2b40e57
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 86 deletions.
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _SwiftSimpleTree_ is part of the [OpenAlloc](https://github.com/openalloc) famil
## SimpleTree

```swift
let foo = SimpleTree<String>(value: "foo")
let foo = SimpleTree(value: "foo")
let bar = foo.addChild(for: "bar")
let baz = bar.addChild(for: "baz")

Expand All @@ -24,6 +24,10 @@ print(baz.getParentValues())
print(foo.getChildValues())

=> ["bar", "baz"]

print(foo.getSelfAndChildValues())

=> ["foo", "bar", "baz"]
```

## Types
Expand All @@ -34,6 +38,15 @@ Types scoped within `SimpleTree`:

- `typealias ValueSet = Set<T>` - a set of values, where `T` is your hashable type.

An enumeration is used for the `traversal` argument in the `getChildren()` methods:

```swift
public enum Traversal {
case depthFirst
case breadthFirst
}
```

## Instance Methods

#### Tree Maintenance
Expand All @@ -44,15 +57,13 @@ Types scoped within `SimpleTree`:

#### Node Retrieval

- `func getChildren(excludeValues: ValueSet) -> [Node]`: Fetch the child nodes of the node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.
- `func getChildren(traversal: Traversal, maxDepth: UInt, excludeValues: ValueSet) -> [Node]`: Fetch the child nodes of the node. Optional list of values for children to be excluded, along with their progeny. Traversal is `.breadthFirst` by default. NOTE: breadth-first with `maxDepth` not yet supported.

- `func getChildren(maxDepth: Int, excludeValues: ValueSet) -> [Node]`: Fetch the child nodes of the node. Optional list of values for children to be excluded, along with their progeny. Traversal is depth-first.
- `func getSelfAndChildren(traversal: Traversal, maxDepth: UInt, excludeValues: ValueSet) -> [Node]`: Fetch the node and its child nodes. Optional list of values for nodes to be excluded, along with their progeny. Traversal is `.breadthFirst` by default. Self is at the first level of depth, so `maxDepth: 0` returns `[]`. NOTE: breadth-first with `maxDepth` not yet supported.

- `func getParent(excludeValues: ValueSet) -> Node?`: Return the immediate parent node, if any. Optional list of parent values to be excluded. A match will cause this function to return nil.

- `func getParents(maxDepth: Int, excludeValues: ValueSet) -> [Node]`: Return the parent nodes, starting with immediate parent. Optional list of parent values to be excluded. A match will exclude further ancestors. Optional limit on depth.

- `func getSelfAndChildren(excludeValues: ValueSet) -> [Node]`: Fetch the node and its child nodes. Optional list of values for nodes to be excluded, along with their progeny. Traversal is breadth-first.
- `func getParents(maxDepth: UInt, excludeValues: ValueSet) -> [Node]`: Return the parent nodes, starting with immediate parent. Optional list of parent values to be excluded. A match will exclude further ancestors. Optional limit on depth.

#### Node Search

Expand All @@ -68,15 +79,14 @@ Types scoped within `SimpleTree`:

#### Value retrieval

- `func getChildValues(excludeValues: ValueSet) -> [T]`: Fetch the values of the child nodes. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.
- `func getChildValues(traversal: Traversal, maxDepth: UInt, excludeValues: ValueSet) -> [T]`: Fetch the values of the child nodes. Optional list of values for children to be excluded, along with their progeny. Traversal is `.breadthFirst` by default. NOTE: breadth-first with `maxDepth` not yet supported.

- `func getChildValues(maxDepth: Int, excludeValues: ValueSet) -> [T]`: Fetch the values of the child nodes. Optional list of values for children to be excluded, along with their progeny. Traversal is depth-first.
- `func getSelfAndChildValues(excludeValues: ValueSet) -> [T]`: Fetch values for the node and its child nodes. Includes value of current node. Optional list of values for nodes to be excluded, along with their progeny. Self is at the first level of depth, so `maxDepth: 0` returns `[]`. Traversal is breadth-first, by default. NOTE: breadth-first with `maxDepth` not yet supported.

- `func getParentValue(excludeValues: ValueSet) -> T?`: Return the value of the immediate parent node, if any. Optional list of parent values to be excluded. A match will cause this function to return nil.

- `func getParentValues(maxDepth: Int, excludeValues: ValueSet) -> [T]`: Return the values of the parent nodes, starting with immediate parent. Optional list of parent values to be excluded. A match will exclude further ancestors. Optional limit on depth.
- `func getParentValues(maxDepth: UInt, excludeValues: ValueSet) -> [T]`: Return the values of the parent nodes, starting with immediate parent. Optional list of parent values to be excluded. A match will exclude further ancestors. Optional limit on depth.

- `func getSelfAndChildValues(excludeValues: ValueSet) -> [T]`: Fetch values for the node and its child nodes. Includes value of current node. Optional list of values for nodes to be excluded, along with their progeny. Traversal is breadth-first.

## See Also

Expand Down
101 changes: 53 additions & 48 deletions Sources/SimpleTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,24 @@ extension SimpleTree {

extension SimpleTree {

public enum Traversal {
case depthFirst
case breadthFirst
}

/// Return the parent nodes, starting with immediate parent.
/// Optional list of parent values to be excluded. A match will exclude further ancestors.
/// Optional limit on depth.
public func getParents(maxDepth: Int = Int.max, excludeValues: ValueSet = ValueSet()) -> [Node] {
public func getParents(maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [Node] {
guard maxDepth > 0 else { return [] }
let iter = self.makeParentIterator()
var depth = maxDepth
var parents = [Node]()
while let parentNode = iter.next() {
if excludeValues.contains(parentNode.value) { break }
parents.append(parentNode)
if depth == 1 { break }
depth -= 1
if depth == 0 { break }
}
return parents
}
Expand All @@ -76,39 +81,42 @@ extension SimpleTree {

/// Fetch the child nodes of the node.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is depth-first.
public func getChildren(maxDepth: Int, excludeValues: ValueSet = ValueSet()) -> [Node] {
guard maxDepth > 0 else { return [] }
/// Traversal is breadth-first by default.
/// NOTE: breadth-first with maxDepth not yet supported.
public func getChildren(traversal: Traversal = .breadthFirst, maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [Node] {
var nodes = [Node]()
for child in children {
if excludeValues.contains(child.value) { continue }
nodes.append(child)
if maxDepth > 1 {
nodes.append(contentsOf: child.getChildren(maxDepth: maxDepth - 1, excludeValues: excludeValues))
switch traversal {
case .depthFirst:
if maxDepth > 0 {
for child in children {
if excludeValues.contains(child.value) { continue }
nodes.append(child)
if maxDepth > 1 {
let _children = child.getChildren(traversal: .depthFirst, maxDepth: maxDepth - 1, excludeValues: excludeValues)
nodes.append(contentsOf: _children)
}
}
}
case .breadthFirst:
guard maxDepth == UInt.max else { fatalError("breadth-first with maxDepth not yet supported") }
let iter = self.makeChildIterator(excludeValues: excludeValues)
while let node = iter.next() {
nodes.append(node)
}
}
return nodes
}

/// Fetch the child nodes of the node.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getChildren(excludeValues: ValueSet = ValueSet()) -> [Node] {
var nodes = [Node]()
let iter = self.makeChildIterator(excludeValues: excludeValues)
while let node = iter.next() {
nodes.append(node)
}
return nodes
}

/// Fetch the node and its child nodes.
/// Optional list of values for nodes to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getSelfAndChildren(excludeValues: ValueSet = ValueSet()) -> [Node] {
guard !excludeValues.contains(self.value) else { return [] }
/// Traversal is breadth-first by default.
/// Self is at the first level of depth, so maxDepth: 0 returns [].
/// NOTE: breadth-first with maxDepth not yet supported.
public func getSelfAndChildren(traversal: Traversal = .breadthFirst, maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [Node] {
guard !excludeValues.contains(self.value), maxDepth > 0 else { return [] }
var nodes: [Node] = [self]
nodes.append(contentsOf: getChildren(excludeValues: excludeValues))
let netMaxDepth = maxDepth - (traversal == .depthFirst ? 1 : 0)
nodes.append(contentsOf: getChildren(traversal: traversal, maxDepth: netMaxDepth, excludeValues: excludeValues))
return nodes
}
}
Expand Down Expand Up @@ -195,10 +203,28 @@ extension SimpleTree {

extension SimpleTree {

/// Fetch the values of the child nodes.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is breadth-first by default.
/// NOTE: breadth-first with maxDepth not yet supported.
public func getChildValues(traversal: Traversal = .breadthFirst, maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [T] {
getChildren(traversal: traversal, maxDepth: maxDepth, excludeValues: excludeValues).map(\.value)
}

/// Fetch values for the node and its child nodes.
/// Includes value of current node.
/// Optional list of values for nodes to be excluded, along with their progeny.
/// Self is at the first level of depth, so maxDepth: 0 returns [].
/// Traversal is breadth-first, by default.
/// NOTE: breadth-first with maxDepth not yet supported.
public func getSelfAndChildValues(traversal: Traversal = .breadthFirst, maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [T] {
getSelfAndChildren(traversal: traversal, maxDepth: maxDepth, excludeValues: excludeValues).map(\.value)
}

/// Return the values of the parent nodes, starting with immediate parent.
/// Optional list of parent values to be excluded. A match will exclude further ancestors.
/// Optional limit on depth.
public func getParentValues(maxDepth: Int = Int.max, excludeValues: ValueSet = ValueSet()) -> [T] {
public func getParentValues(maxDepth: UInt = UInt.max, excludeValues: ValueSet = ValueSet()) -> [T] {
getParents(maxDepth: maxDepth, excludeValues: excludeValues).map(\.value)
}

Expand All @@ -207,25 +233,4 @@ extension SimpleTree {
public func getParentValue(excludeValues: ValueSet = ValueSet()) -> T? {
getParent(excludeValues: excludeValues)?.value
}

/// Fetch the values of the child nodes.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is depth-first.
public func getChildValues(maxDepth: Int, excludeValues: ValueSet = ValueSet()) -> [T] {
getChildren(maxDepth: maxDepth, excludeValues: excludeValues).map(\.value)
}

/// Fetch the values of the child nodes.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getChildValues(excludeValues: ValueSet = ValueSet()) -> [T] {
getChildren(excludeValues: excludeValues).map(\.value)
}

/// Fetch values for the node and its child nodes.
/// Optional list of values for nodes to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getSelfAndChildValues(excludeValues: ValueSet = ValueSet()) -> [T] {
getSelfAndChildren(excludeValues: excludeValues).map(\.value)
}
}
Loading

0 comments on commit 2b40e57

Please sign in to comment.