代码之家  ›  专栏  ›  技术社区  ›  The_Ghost

在F中插入“简单”和/或“更好”

  •  0
  • The_Ghost  · 技术社区  · 16 年前

    我想先问一些关于在f中简化不同表达式的问题。

    任何人都有更好和/或更简单地实现insertat的想法(参数也可以重新排序)。可以使用列表或序列。

    下面是一些开始实现:

    let insertAt x xs n = Seq.concat [Seq.take n xs; seq [x]; Seq.skip n xs]
    
    5 回复  |  直到 16 年前
        1
  •  2
  •   Dario    16 年前

    Dannyasher发布的实现是非- tail-recursive 一个。为了提高函数的效率,我们必须引入一个显式的accumulator参数,使函数尾递归,并允许编译器优化递归开销:

    let insertAt =
        let rec insertAtRec acc n e list = 
            match n, list with
            | 0, _     -> (List.rev acc) @ [e] @ list
            | _, x::xs -> insertAtRec (x::acc) (n - 1) e xs
            | _        -> failwith "Index out of range"
    
        insertAtRec []
    
        2
  •  2
  •   Juliet    16 年前

    使用seq进行尾部递归:

    let rec insertAt = function
        | 0, x, xs -> seq { yield x; yield! xs }
        | n, x, xs -> seq { yield Seq.hd xs; yield! insertAt (n-1, x, Seq.skip 1 xs) }
    
        3
  •  1
  •   Daniel Asher    16 年前

    以下是haskell列表插入的F实现:

    let rec insertAt x ys n =
        match n, ys with 
        | 1, _      
        | _, []     -> x::ys
        | _, y::ys  -> y::insertAt x ys (n-1)
    
    let a = [1 .. 5]
    let b = insertAt 0 a 3
    let c = insertAt 0 [] 3
    
    > 
    val a : int list = [1; 2; 3; 4; 5]
    val b : int list = [1; 2; 0; 3; 4; 5]
    val c : int list = [0]
    

    我的haskell不足以知道在haskell函数中传递空列表的情况是否得到了正确的处理。在f中,我们明确地处理第二个匹配案例中的空列表。

    丹尼

        4
  •  1
  •   ssp    16 年前

    如果您真的想使用序列:

    let insertAt x ys n =
      let i = ref n
      seq {
        for y in ys do
        decr i
        if !i = 0 then yield x
        yield y
      }
    

    在所有其他情况下,丹尼亚舍的回答肯定是更好更快。

        5
  •  0
  •   RobV    16 年前

    来自haskell wiki- http://www.haskell.org/haskellwiki/99_questions/21_to_28

    insertAt :: a -> [a] -> Int -> [a]
    insertAt x ys     1 = x:ys
    insertAt x (y:ys) n = y:insertAt x ys (n-1)
    

    我不是一个F程序员,所以我不知道F的等效语法,但这是一个很好的插入式递归定义。