假设我有一个简单的链接列表:
class Node {
var parent: Node?
}
// Create the chain: a <- b <- c
let a = Node()
let b = Node(parent: a)
let c = Node(parent: b)现在,我想将c转换为数组([c, b, a]),这样我就可以使用其他高阶函数,比如map。
什么方法可以从通常被调用的链接列表中生成数组?
有没有一种方法可以使用其他高阶函数来实现这一点,而不是使用循环呢?
我能想到的唯一实现回到使用循环:
func chain<T>(_ initial: T, _ next: (T) -> T?) -> [T] {
var result = [initial]
while let n = next(result.last!) {
result.append(n)
}
return result
}
chain(c) { $0.parent } // == [c, b, a]我想知道是否有一种内置的方法来使用map/减/等函数来获得相同的结果。
发布于 2020-10-18 23:09:36
您可以使用sequence(first:next:)创建一个Sequence,然后使用Array()将该序列转换为一个数组:
let result = Array(sequence(first: c, next: { $0.parent }))或相当于:
let result = Array(sequence(first: c, next: \.parent))您可以使用它来实现chain
func chain<T>(_ initial: T, _ next: @escaping (T) -> T?) -> [T] {
Array(sequence(first: initial, next: next))
}但我会直接用它。
注:--如果您只想调用map,则不需要将序列转换为Array。您只需将.map应用于序列。
例如,下面是一个无用的map,它用一个1表示链接列表中的每个节点
let result = sequence(first: c, next: \.parent).map { _ in 1 }发布于 2020-10-19 06:41:44
您可以使Node成为一个“变性”序列,这将自动带来所有高阶函数:map、filter、reduce、flatMap等。
class Node {
var parent: Node?
var value: String
init(parent: Node? = nil, value: String = "") {
self.parent = parent
self.value = value
}
}
extension Node: Sequence {
struct NodeIterator: IteratorProtocol {
var node: Node?
mutating func next() -> Node? {
let result = node
node = node?.parent
return result
}
}
func makeIterator() -> NodeIterator {
NodeIterator(node: self)
}
}
// Create the chain: a <- b <- c
let a = Node(value: "a")
let b = Node(parent: a, value: "b")
let c = Node(parent: b, value: "c")
// each node behaves like its own sequence
print(c.map { $0.value }) // ["c", "b", "a"]
print(b.map { $0.value }) // ["b", "a"]https://stackoverflow.com/questions/64419059
复制相似问题