获取f#中列表的最后一个元素

joe*_*sid 4 .net f# reverse function list

我想获取列表的最后一个元素,我的逻辑是反转列表并获得它的头部:

module Program1 = 

    let last list =
        let newList=List.rev list;
        List.head newList;
        newList 

    let mainP1()=
        let list= [ 1; 2; 3] 
        printfn "Ultimul element al listei %A este %A" list (last list )
Run Code Online (Sandbox Code Playgroud)

但它给了我这个错误

Error       Type mismatch. Expecting a
    unit list    
but given a
    int list    
The type 'unit' does not match the type 'int'   
Run Code Online (Sandbox Code Playgroud)

谁能帮帮我吗?

Fyo*_*kin 5

在这里拆包有很多东西.

首先,您的功能不会返回您想要返回的内容.看那最后一行,那个说newList什么?这是你的函数的返回值.函数体的最后一行是它的返回值.所以你要返回反向列表,而不是最后一个元素.

其次,由于你没有返回List.head通话结果,你忽略了它.没有做任何结果.忽略.F#编译器试图在这里帮助你:如果你忽略了一个值,那就意味着你做错了,如果你这样做,F#会抱怨(发出警告).

但是该规则有一个例外:您可以忽略类型的值unit.逻辑是,如果你有一个类型的值unit,你必须得到它作为产生副作用的结果.因为如果没有副作用,并且没有结果值(unit意味着"没有价值"),那么重点是什么?

所以,编译器会这样想:如果你忽略了一个值,那么该值必须是类型unit.而且既然List.head newList是类型unit,那么newList必须是类型unit list.因此,list必须是类型unit list.因此,您的函数是类型的unit list -> unit list(即它接受一个unit list参数并返回另一个unit list作为结果).

既然你正试图将int list一个函数传递给一个带有a的函数unit list,那么编译器就无法忍受了:Expecting a unit list but given a int list.

最后,为了获得最后一个值反转列表是非常浪费的!你正在重新分配你并不真正需要的大量内存.实现这一目标的一种较少浪费的方法是通过使用递归.以这种方式思考:单元素列表的最后一个元素是一个元素,而较长列表的最后一个元素是它尾部的最后一个元素.我们可以在F#中直接写出:

let rec last list =
  match list with
  | [x] -> x   // The last element of one-element list is the one element
  | _::tail -> last tail   // The last element of a longer list is the last element of its tail
  | _ -> failwith "Empty list"   // Otherwise fail
Run Code Online (Sandbox Code Playgroud)

此外,还有一个现成的功能List.last,你可以使用(除非这是作业,在这种情况下你应该在问题中提到).

let mainP1()=
  let list= [ 1; 2; 3] 
  printfn "Ultimul element al listei %A este %A" list (List.last list)
Run Code Online (Sandbox Code Playgroud)

但要注意,列表中可能没有最后一个元素 - 如果列表为空.在这种情况下,List.last(以及List.head)会因异常而崩溃,这通常不是一个好主意.如果您需要处理空列表案例,请查看List.tryLast:

let mainP1()=
  let list= [1; 2; 3] 
  match List.tryLast list with
  | Some x -> printfn "Ultimul element al listei %A este %A" list x
  | None -> printfn "Lista %A este goal?" list
Run Code Online (Sandbox Code Playgroud)

  • 一个名为`FSharp.Collections.List <'T>`的不可变链表对于随机访问不是那么有效:必须遍历整个列表,因此O(n).`List.rev`并不比那更好或更糟. (3认同)