【问题标题】:Value of the last element of a list列表最后一个元素的值
【发布时间】:2010-11-13 14:06:33
【问题描述】:

如何获取List最后一个元素的值?我注意到 List.hd(或 .Head)返回一个项目,而 List.tl(或 .Tail)返回一个 List。

是 rev 列表并获得 hd 的唯一方法吗?谢谢。

【问题讨论】:

    标签: list f# reverse tail


    【解决方案1】:

    试试这个功能。它使用递归,尽管由于它是尾递归,因此无论如何它都针对迭代进行了优化。无论如何,它很可能比反转整个列表(使用List.rev)更快。

    let rec last = function
        | hd :: [] -> hd
        | hd :: tl -> last tl
        | _ -> failwith "Empty list."
    

    不过,Pavel Minaev 的回答绝对值得考虑。尽管如此,您请求的算法可能在极少数情况下有用,并且是完成任务的最有效方法。

    【讨论】:

    • 由于这是尾递归算法,编译器会将其实现为高效的while循环。关于数据结构的选择,我倾向于同意 Pavel,但如果您需要使用列表,那么这是正确的方法。
    • @dahlbyk:没错。我本来想记下这件事,但我好像忘记了——我现在要添加它。
    • 必须是"let rec last tl = function",function last 没有参数
    【解决方案2】:

    一般来说,如果你需要这样做,你就做错了。由于 F# 列表是单链接的,因此访问最后一个元素的成本很高 - O(N),其中 N 是 list 的大小。尝试重写您的算法,以便您始终访问 first 元素,而不是最后一个元素(即O(1))。如果您不能这样做,很有可能您为数据结构选择的list 一开始就不正确。

    【讨论】:

      【解决方案3】:

      使用 List.reduce 是一种快速而肮脏的方法。假设列表名为ls

      let lastElement ls = List.reduce (fun _ i -> i) ls
      

      关于效率,我同意 Pavel。

      【讨论】:

        【解决方案4】:

        基于米奇的回答的更简洁的版本:

        let lastItem = myList |> List.rev |> List.head
        

        myList 列表被发送到List.rev 函数。然后由List.head处理结果

        【讨论】:

          【解决方案5】:

          同意,获取list 的最后一个元素或任何其他“可枚举”序列的效率并不高。也就是说,这个函数已经存在于Seq模块Seq.last中。

          【讨论】:

          • 即使没有,也很容易定义:module Seq = let last xs = Seq.reduce (fun _ x -> x) xs
          【解决方案6】:

          作为一名 F# 开发新手,我不明白执行以下操作有什么害处

          let mylist = [1;2;3;4;5]
          
          let lastValue = mylist.[mylist.Length - 1]
          

          本质上势在必行?可以,但不需要递归。

          【讨论】:

          • 这将花费相当长的时间,因为List.length 需要遍历列表,访问也是如此。基本上你必须遍历列表两次。
          • 我刚查了源代码,你是对的。然而,为什么一个属性会计算这个值,这超出了我的理解。在知道元素的数量时,也许我希望列表具有与数组相同的行为。
          • 列表不会缓存它们的大小 - 这会显着减少它们在内存中的大小,因为您需要缓存每个元素的大小。
          • 尺寸是指长度吗?我的印象是列表有一个数组作为后备存储,它创建一个新数组并在大小超过其容量时复制元素。
          • 以数组作为后备存储的列表是System.Collections.Generic.List<_>,这些与F#列表不同,并且具有不同的性能目标。
          【解决方案7】:

          在 F# 中使用列表的常规方法是使用递归。列表中的第一项是头部(显然),列表的其余部分是尾部(与最后一项相反)。因此,当一个函数接收到一个列表时,它会处理 head,然后递归处理列表的其余部分(tail)。

          let reversedList = List.rev originalList
          let tailItem = List.hd reversedList
          

          【讨论】:

            【解决方案8】:

            我觉得你可以写

            list.[0..list.Length-1]
            

            【讨论】:

              【解决方案9】:

              您可以调用 List.Head 来获取列表的第一个元素,这样以下表达式的计算结果为 true:

              let lst = [1;2;3;4;5]
              List.head lst = 1
              

              但是,调用 List.Tail 将返回列表中第一个元素之后的每个元素,因此以下表达式为真:

              let lst = [1;2;3;4;5]
              List.tail lst = [2;3;4;5]
              

              就像其他人提到的那样,F# 中没有一种有效的方法来获取列表的尾部,基本列表在构建时并未考虑到该功能。如果你真的想得到最后一个元素,你必须先反转你的列表,然后取新的头(即前一个尾)。

              let lst = [1;2;3;4;5]
              (List.head (List.rev lst) ) = 5
              

              【讨论】:

                【解决方案10】:

                下面的代码对我来说很好用,我有一个整数数组,想从第 5 个项目开始,然后减去项目编号

                Sum of [Array(xi) - Array(xi-5)] where i start at 5
                

                使用的代码是:

                series |> Array.windowed 5
                       |> Array.fold (fun s x -> 
                                            (x |> Array.rev |> Array.head) -  (x |> Array.head) + s) 0
                       |> float
                

                【讨论】:

                  【解决方案11】:

                  这是一个非常古老的问题,但以防万一有人来这里:

                  使用 FSharp 5,您可以执行 x.[^index],其中索引将从数组/列表的末尾开始。

                  let a = [1;2;3;4;5;6;7;8;9]
                  
                  a.[^0] is 9
                  a.[^1] is 8
                  etc
                  

                  【讨论】:

                  • 这是一个不错的功能,但我也想知道这是否也会遍历列表两次。当然,这并不意味着此功能不好,但可能不是检索最后一个元素的最佳选择。
                  • 除非存储列表长度;我还没有查看实现,但这绝对是一个有效的问题
                  猜你喜欢
                  • 2022-01-07
                  • 2018-03-10
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-07-12
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-11-09
                  • 1970-01-01
                  相关资源
                  最近更新 更多