Skip to content

Commit

Permalink
various changes to make api more consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
Reed Es committed Nov 18, 2021
1 parent b9ec622 commit ee30544
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 134 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/Packages
/*.xcodeproj
xcuserdata/
.swiftpm/
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ _SwiftSimpleTree_ is part of the [OpenAlloc](https://github.com/openalloc) famil

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

print(foo.getFirst(forValue: "baz")?.value)
print(foo.getFirst(for: "baz")?.value)

=> "baz"

Expand All @@ -28,6 +28,8 @@ print(foo.getAllChildValues())

## Types

Types scoped within `SimpleTree`:

- `typealias Node = SimpleTree<T>` - a tree node, where `T` is your hashable type.

- `typealias ValueSet = Set<T>` - a set of values, where `T` is your hashable type.
Expand All @@ -38,46 +40,44 @@ print(foo.getAllChildValues())

- `init(value: T)`: Initialize a new tree (containing the specified value at the root)

- `func addChild(forValue: T) -> Node`: Append a new node (containing the specified value) to our list of children
- `func addChild(for: T) -> Node`: Append a new node (containing the specified value) to our list of children

#### Node Retrieval

- `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 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(maxDepth: Int, excludeValues: ValueSet) -> [Node]`: Fetch child nodes. Optional list of values for children to be excluded, along with their progeny. Traversal is depth-first, with optional limit.
- `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, with optional limit.

#### Iterators
- `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 makeChildIterator(excludeValues: ValueSet) -> AnyIterator<Node>`: Create a iterator to traverse through the children (grandchildren, etc.) of the current node. Traversal is breadth-first. With short circuit of child branches on exclude filter.
- `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 makeParentIterator() -> AnyIterator<Node>`: Create a iterator to traverse up the tree through the parents of the current node, starting with the most recent parent, if any.
- `func getAll(excludeValues: ValueSet) -> [Node]`: Fetch the node and its child nodes. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.

#### Iterative Node Search
#### Node Search

- `func getFirst(forValue: T) -> Node?`: Traverse from the current node to find the first node with the specified value. Includes current node. Traversal is breadth-first.
- `func getFirst(for: T) -> Node?`: Traverse from the current node to find the first node with the specified value. Traversal is breadth-first.

- `func getFirstChild(forValue: T) -> Node?`: Traverse the children from the current node to find the first child (grandchild, etc.) with the specified value. Traversal is breadth-first.
- `func getFirstChild(for: T) -> Node?`: Traverse the children from the current node to find the first child (grandchild, etc.) with the specified value. Traversal is breadth-first.

#### Iterative Node Retrieval
#### Iterators

- `func getAll(excludeValues: ValueSet) -> [Node]`: Flatten tree from current node. Includes current node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.
- `func makeChildIterator(excludeValues: ValueSet) -> AnyIterator<Node>`: Create a iterator to traverse through the children (grandchildren, etc.) of the current node. Traversal is breadth-first. With short circuit of child branches on exclude filter.

- `func getAllChildren(excludeValues: ValueSet) -> [Node]`: Get all the child nodes from the current node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.
- `func makeParentIterator() -> AnyIterator<Node>`: Create a iterator to traverse up the tree through the parents of the current node, starting with the most recent parent, if any.

#### Value retrieval

- `func getAllChildValues(excludeValues: ValueSet) -> [T]`: Get all the child values from the current node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.

- `func getAllValues(excludeValues: ValueSet) -> [T]`: Flatten tree from current node. Includes value of current node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.
- `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(maxDepth: Int, excludeValues: ValueSet) -> [T]`: Fetch child values. Optional list of values for children to be excluded, along with their progeny. Traversal is depth-first, with optional limit.
- `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, with optional limit.

- `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 getAllValues(excludeValues: ValueSet) -> [T]`: Fetch values for the node and its child nodes. Includes value of current node. Optional list of values for children to be excluded, along with their progeny. Traversal is breadth-first.

## See Also

Swift open-source libraries (by the same author):
Expand Down
82 changes: 39 additions & 43 deletions Sources/SimpleTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class SimpleTree<T> where T: Equatable & Hashable {
extension SimpleTree {

/// Append a new node (containing the specified value) to our list of children
public func addChild(forValue value: T) -> Node {
public func addChild(for value: T) -> Node {
let nuChild = Node(value: value)
children.append(nuChild)
nuChild.parent = self
Expand Down Expand Up @@ -74,10 +74,10 @@ extension SimpleTree {
getParents(maxDepth: 1, excludeValues: excludeValues).first
}

/// Fetch child nodes.
/// Fetch the child nodes of the node.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is depth-first, with optional limit.
public func getChildren(maxDepth: Int = Int.max, excludeValues: ValueSet = ValueSet()) -> [Node] {
public func getChildren(maxDepth: Int, excludeValues: ValueSet = ValueSet()) -> [Node] {
guard maxDepth > 0 else { return [] }
var nodes = [Node]()
for child in children {
Expand All @@ -89,6 +89,28 @@ extension SimpleTree {
}
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 children to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getAll(excludeValues: ValueSet = ValueSet()) -> [Node] {
guard !excludeValues.contains(self.value) else { return [] }
var nodes: [Node] = [self]
nodes.append(contentsOf: getChildren(excludeValues: excludeValues))
return nodes
}
}

// MARK: - Iterators
Expand All @@ -100,9 +122,9 @@ extension SimpleTree {
var node: Node? = self.parent
return AnyIterator { () -> Node? in
guard let _node = node else { return nil }
let currentNode = _node
let nextNode = _node
node = _node.parent // okay if nil
return currentNode
return nextNode
}
}

Expand Down Expand Up @@ -144,13 +166,13 @@ extension SimpleTree {
}
}

// MARK: - Iterative Node Search
// MARK: - Node Search

extension SimpleTree {

/// Traverse the children from the current node to find the first child (grandchild, etc.) with the specified value.
/// Traversal is breadth-first.
public func getFirstChild(forValue value: T) -> Node? {
public func getFirstChild(for value: T) -> Node? {
let iter = self.makeChildIterator()
while let node = iter.next() {
if node.value == value {
Expand All @@ -160,38 +182,12 @@ extension SimpleTree {
return nil
}

/// Traverse from the current node to find the first node with the specified value. Includes current node.
/// Traverse from the current node to find the first node with the specified value.
/// Includes current node.
/// Traversal is breadth-first.
public func getFirst(forValue value: T) -> Node? {
public func getFirst(for value: T) -> Node? {
guard self.value != value else { return self }
return getFirstChild(forValue: value)
}
}

// MARK: - Iterative Node Retrieval

extension SimpleTree {

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

/// Flatten tree from current node. Includes current node.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getAll(excludeValues: ValueSet = ValueSet()) -> [Node] {
guard !excludeValues.contains(self.value) else { return [] }
var nodes: [Node] = [self]
nodes.append(contentsOf: getAllChildren(excludeValues: excludeValues))
return nodes
return getFirstChild(for: value)
}
}

Expand All @@ -212,21 +208,21 @@ extension SimpleTree {
getParent(excludeValues: excludeValues)?.value
}

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

/// Get all the child values from the current node.
/// 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 getAllChildValues(excludeValues: ValueSet = ValueSet()) -> [T] {
getAllChildren(excludeValues: excludeValues).map(\.value)
public func getChildValues(excludeValues: ValueSet = ValueSet()) -> [T] {
getChildren(excludeValues: excludeValues).map(\.value)
}

/// Flatten tree from current node. Includes value of current node.
/// Fetch values for the node and its child nodes.
/// Optional list of values for children to be excluded, along with their progeny.
/// Traversal is breadth-first.
public func getAllValues(excludeValues: ValueSet = ValueSet()) -> [T] {
Expand Down
Loading

0 comments on commit ee30544

Please sign in to comment.