public extension Graph { // MARK: - Value Mapper func map(_ transform: (NodeValue) throws -> MappedValue) rethrows -> Graph { let idsWithMappedValues = try nodes.map { ($0.id, try transform($0.value)) } return .init(valuesByID: .init(uniqueKeysWithValues: idsWithMappedValues), edges: edges) } // MARK: - Edge Filters func filteredEdges(_ isIncluded: EdgeIDs) -> Self { var result = self result.filterEdges(isIncluded) return result } mutating func filterEdges(_ isIncluded: EdgeIDs) { filterEdges { isIncluded.contains($0.id) } } func filteredEdges(_ isIncluded: (Edge) throws -> Bool) rethrows -> Self { var result = self try result.filterEdges(isIncluded) return result } mutating func filterEdges(_ isIncluded: (Edge) throws -> Bool) rethrows { try edges.forEach { if try !isIncluded($0) { removeEdge(with: $0.id) } } } // MARK: - Value Filters func filtered(_ isIncluded: (NodeValue) throws -> Bool) rethrows -> Self { var result = self try result.filter(isIncluded) return result } mutating func filter(_ isIncluded: (NodeValue) throws -> Bool) rethrows { try filterNodes { try isIncluded($0.value) } } // MARK: - Node Filters func filteredNodes(_ isIncluded: NodeIDs) -> Self { var result = self result.filterNodes(isIncluded) return result } mutating func filterNodes(_ isIncluded: NodeIDs) { filterNodes { isIncluded.contains($0.id) } } func filteredNodes(_ isIncluded: (Node) throws -> Bool) rethrows -> Self { var result = self try result.filterNodes(isIncluded) return result } mutating func filterNodes(_ isIncluded: (Node) throws -> Bool) rethrows { try nodes.forEach { if try !isIncluded($0) { removeNode(with: $0.id) } } } }