【问题标题】:Swapping every pair of items in an F# list交换 F# 列表中的每一对项目
【发布时间】:2011-11-19 20:40:55
【问题描述】:

我很肯定有更好的方法来成对交换列表中的项目( [1;2;3;4] -> [2;1;4;3] ),因为我做的太多了根据我的喜好附加,但我不确定如何最好地做到这一点。

let swapItems lst =
    let f acc item =
        match acc with
        | [] -> [item]
        | hd :: next :: tl when tl <> [] -> [next] @ tl @ [item;hd]
        | _ -> item :: acc
    List.fold f [] lst

我该如何改进呢?这仅适用于具有偶数长度的列表。

【问题讨论】:

    标签: f# functional-programming sequences


    【解决方案1】:

    最简单的解决方案:

    let rec swapItems = function
      | a::b::xs -> b::a::swapItems xs
      | xs -> xs
    

    我喜欢将变量的名称命名为“复数”列表等序列,例如xs 而不是 x

    注意,这不是尾递归,所以如果你给它一个很长的列表,它会堆栈溢出。

    【讨论】:

      【解决方案2】:

      这个呢:

      let rec swapItems = function
          | []
          | _::[] as l -> l
          | a::b::t ->
              b::a::(swapItems t)
      

      ?

      【讨论】:

      • 我觉得这样做稍微优雅一点function |a::b::t -&gt; b::a::t |a -&gt; failwith "not enough elements"
      • 非常感谢,并诅咒 F# 总是让事情变得如此简单;)
      • @jpalmer,我不知道他为什么要这样做,但我推测他也希望这个解决方案适用于奇数个元素的列表。
      • @Ramon - 我没有意识到他也重新订购了4,3 - 我的解决方案不起作用,尽管如果您将前两个案例移动到您的函数中,您仍然可以将它们组合到结束
      • @jpalmer,是的,这是风格问题。我尽量避免使用最后条款匹配案例。
      【解决方案3】:

      使用高阶函数可以这样做:

      let swapItems l =
          l |> List.toSeq |> Seq.pairwise
          |> Seq.mapi (fun i (a,b) -> if i % 2 = 0 then seq [b;a] else Seq.empty)
          |> Seq.concat |> Seq.toList
      

      【讨论】:

      • 一个列表就是一个序列,你不必调用List.toSeq。我不确定它是否会做一些事情(不仅仅是强制类型检查器)。
      猜你喜欢
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多