List F#折叠,同时使用cons(::)而不是concat(@)创建列表

List F#折叠,同时使用cons(::)而不是concat(@)创建列表,list,f#,concat,fold,List,F#,Concat,Fold,我有下面的函数,它满足我的需要。但是is使用concat(@)操作符,它是O(n),而不是O(1)作为(::)操作符 chgLstAndLast返回最后一个值和生成的结果列表: val chgLstAndLast : float * float list = (0.989604, [-0.01; -0.0198; 0.019404]) 我想从三个方面改进以上内容 使用con(:)而不是concat(@) 将列表累积从myFunc移动到list.fold操作 确保生成的列表顺序与上述相同(即最后

我有下面的函数,它满足我的需要。但是is使用concat(@)操作符,它是O(n),而不是O(1)作为(::)操作符

chgLstAndLast返回最后一个值和生成的结果列表:

val chgLstAndLast : float * float list = (0.989604, [-0.01; -0.0198; 0.019404])
我想从三个方面改进以上内容

  • 使用con(:)而不是concat(@)
  • 将列表累积从myFunc移动到list.fold操作
  • 确保生成的列表顺序与上述相同(即最后一个结果位于列表末尾,而不是标题)
  • 例如,我想这样写一个
    myFunc

    let myFunc s m cs =  
        let n = s * m
        let c = n - s // single element, but not as list
        (n, c) // No concat here
    

    但是当我这样做时,我不知道如何在Fold函数中使用(::)cons

    如果我正确理解了您的代码,您要做的是在保留所有中间结果的同时进行
    折叠。这几乎就是
    List.scan所做的;它还返回初始状态

    让chglstandast数据=
    让我们来看看m=
    设n=s*m
    n、 n-s
    让processedData=data |>List.scan(乐趣,乐趣->内部序号)(1.0,1.0)
    让lastResult=processedData |>List.reduce(乐趣->n)
    让seq=processedData |>List.tail |>List.map snd
    最后结果,seq
    
    为了进一步解释这段代码:首先我声明了一个内部函数,使代码对外部世界更干净(假设其他代码不需要
    myFunc
    ),然后我使用
    scan
    fold
    获取所有中间结果,这是执行fold+累加器技巧的内置方法。

    最后一个值是通过
    reduce
    技巧获得的,因为没有内置的“last of list”函数,中间结果是处理数据的第二部分,第一个元素是初始状态。

    list.scan似乎正是我想要的。非常感谢。内部功能确实需要突破,但这相当容易。一个问题是关于最后的结果。为什么不让lastResult=fst processedData。[processedData.Length-1]而不是List.reduce。使用reduce有好处吗?因为F#的列表是一个链表,长度是O(n),索引也是O(n),所以List[List.length-1]必须遍历列表两次。Reduce只遍历它一次。如果你想让它更干净,写一个递归的
    列表.last
    函数(非常简单)。现在我明白了。非常感谢。您关于
    Reduce
    vs我的版本的解释非常有用。
    let myFunc s m cs =  
        let n = s * m
        let c = n - s // single element, but not as list
        (n, c) // No concat here