【问题标题】:Is there a high-order function to convert a linked list to an array?是否有将链表转换为数组的高阶函数?
【发布时间】:2020-10-18 22:46:00
【问题描述】:

假设我有一个简单的链表:

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/reduce/etc 之类的函数。得到相同的结果。

【问题讨论】:

    标签: swift functional-programming


    【解决方案1】:

    您可以使用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 }
    

    【讨论】:

    • 或者干脆sequence(first: c, next: \.parent)
    【解决方案2】:

    您可以将Node 设为“变性”序列,这将自动带来所有高阶函数:mapfilterreduceflatMap 等。

    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"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-20
      • 2021-04-09
      • 1970-01-01
      相关资源
      最近更新 更多