数组最后一个元素的简洁表示法

5
是否有一种简洁的表示法来访问数组的最后一个元素,类似于C++中的std::vector::back()?我需要写这样的代码吗:
```c++ array[array.length - 1] ```
veryLongArrayName.[veryLongArrayName.Length-1]

每次?

4
你可以使用 Seq.last veryLongArrayName,但效率远不如直接编写一个内联函数并每次调用它。 - ildjarn
有趣的是,我刚刚重新阅读了我的问题,并想到了同样的答案。唯一的缺点是会产生主观语言方言:有些人会使用“back”,而其他人可能更喜欢“last”等等。 - Paul Jurczak
1
Seq.last 已经在这里设置了先例;back 是 C++ 的一个术语,主要是由于标准库需要区分迭代器和值(即 end vs. back)。 - ildjarn
1
@ildjarn,我认为你的建议是正确的答案。你能把它发表为一个答案吗(这样我们就可以点赞并让Paul接受它了:-))? - Tomas Petricek
3个回答

10

从评论扩展

内置选项为Seq.last veryLongArrayName,但请注意这是O(N)而不是O(1),因此除了最小的数组外,对于实际使用来说可能过于低效。

话虽如此,自己抽象这个功能也没有什么害处:

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Array =
    let inline last (arr:_[]) = arr.[arr.Length - 1]

现在,您可以使用Array.last veryLongArrayName而不会有任何额外的开销,同时保持代码非常惯用和易读。

太好了!我会将它复制粘贴到有用技巧文件中。我几天前才开始接触F#,所以需要再花几天时间来了解这些属性的含义。 - Paul Jurczak
@Paul:这些属性并不是必需的,我只是添加它们是因为内置的F# Array模块有它们。实际上,第一个属性会导致Array模块在IL中被命名为ArrayModule(即如果它是公共的,其他语言将如何看待它),而第二个属性则禁止执行open Array - ildjarn

9

我在官方文档中没有找到,但是 F# 4 似乎已经内置了 Array.last 方法:

/// Returns the last element of the array.
/// array: The input array.
val inline last : array:'T [] -> 'T

访问Github上的实现代码链接


谢谢你让我知道。我认为这是 F# 核心的一个有用的补充。 - Paul Jurczak
F# 4 实现了 Seq、List 和 Array 的匹配功能。由于 Seq.last 已经存在,因此需要创建 Array.last。 - Lamarth

6
作为对 _[] 函数的一种替代,您也可以为 IList<'T> 编写扩展属性:
open System.Collections.Generic

[<AutoOpen>]
module IListExtensions =
    type IList<'T> with 
        member self.Last = self.[self.Count - 1]

let lastValue = [|1; 5; 13|].Last // 13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接