【问题标题】:F#: Get length of tupleF#:获取元组的长度
【发布时间】:2015-09-23 14:37:23
【问题描述】:

有什么方法可以获取元组长度。 我的意思是让a=(1,2,3) 之类的东西。我必须得到3

我使用以下代码将元组转换为列表并尝试获取列表的长度,但结果为option 类型,我无法使用它。

let tupleToList t = 
    if Microsoft.FSharp.Reflection.FSharpType.IsTuple(t.GetType()) 
        then Some (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields t |> Array.toList)
        else None

【问题讨论】:

  • 使用当前方法的一个简单解决方案(不管它可能是最好的)是消除或解开正在引入的“选项”;要么在那里(例如,为非元组返回 0 或 -1,否则返回列表的长度)或在使用站点(例如,将其视为“可能代表或可能不代表列表”的任何选项)。
  • 首先,元组的 length 在它的类型中是隐含的 - 这就是为什么没有反射 trickery (或其他一些运行时作弊 ;)) - 但在这种情况下,如果您对该函数的输入不是一个元组,那么一个简单的 tupleToList >> Option.map (List.length) 将为您提供一个长度为 lNone 的元组。

标签: f# f#-interactive


【解决方案1】:

正如这里给出的,tupleToList 函数返回obj list option,所以你将不得不处理None 的情况。

非元组的长度应该是多少?

为了便于讨论,我们将长度设置为0。在这种情况下,您可以使用Option.mapOption.fold 获取元组的长度(和其他值)。例子:

> (1, "2") |> tupleToList |> Option.map List.length |> Option.fold (+) 0;;
val it : int = 2

> ("1", 2, 3.0) |> tupleToList |> Option.map List.length |> Option.fold (+) 0;;
val it : int = 3

> "Not a tuple" |> tupleToList |> Option.map List.length |> Option.fold (+) 0;;
val it : int = 0

如果愿意,您可以将表达式Option.map List.length |> Option.fold (+) 0 绑定到一个函数。

【讨论】:

    【解决方案2】:

    如果您的意图只是为任何元组参数获取一个元组长度,并为非元组参数获取一些可区分的其他数字,例如0,那么无需费心将元组完全转换为列表;直接

    let tupleLength t =
        if Microsoft.FSharp.Reflection.FSharpType.IsTuple(t.GetType()) 
        then (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields t |> Array.length)
        else 0
    

    给你这样的签名:tupleLength: t:'a -> int

    在 FSI 中测试它:

    > (1,'a',10.0) |> tupleLength;;
    val it : int = 3
    
    > ("a",["b";"c";"d"]) |> tupleLength;;
    val it : int = 2
    

    但是

    ["a","b","c","d"] |> tupleLength;;
    val it : int = 0
    

    【讨论】:

      【解决方案3】:

      假设它总是发送元组,我认为以下更简单。

      let t = 1,2,3
      
      
      let inline countTuples t = 
       t.GetType().GetGenericArguments().Length
      
      countTuples t
      //val it : int = 3
      
      let a = 4
      
      countTuples a
      //val it : int = 0
      
      let list = ["4", "5"]
      
      countTuples list
      //val it : int = 1
      

      如果不总是元组,并且可能有通用参数(最后一个例子),那么检查元组当然是必要的......

      【讨论】:

        猜你喜欢
        • 2019-04-08
        • 2012-04-20
        • 1970-01-01
        • 2020-06-08
        • 2015-08-05
        • 2015-08-14
        • 1970-01-01
        • 2023-03-26
        • 1970-01-01
        相关资源
        最近更新 更多