F#中的列表操作

Dan*_*nny 6 recursion f# list

我希望这个功能的作用是:

  1. 生成由count指定的长度的随机整数列表

  2. 生成另一个随机数以替换列表的第一个元素

  3. 对列表进行排序

  4. 拆分列表减半,丢弃下半场

  5. 丢弃列表的第一个元素

  6. 除非列表为空,否则重复2-5

到目前为止我(但没有工作)的内容如下.它有什么关系?

let go count =
    let rec cut l = 
        if List.length l = 0 then l
        printfn "%A" l
        let list = System.Random().Next(100)::List.tail l
        let cut list = 
            let firstHalf= list |> Seq.take (List.length list / 2) |> Seq.toList
            firstHalf
        let listSorted = List.sort list
        cut (List.tail listSorted)
    let r = System.Random()
    let list1 = List.init count (fun numbers -> r.Next(100))
    printfn "List = %A" list1
    cut list1
Run Code Online (Sandbox Code Playgroud)

cfe*_*ern 7

一些提示:

  • 不要通过List.length L = 0测试列表是否为空.每个测试将花费与列表中元素的数量一样长的时间.用模式匹配测试,这几乎是瞬间的:

  • 每次cut调用函数时都不要实例化随机数生成器的新实例:let list = System.Random()....这样做意味着您可能会获得相同的数字(每个实例都会使用当前系统时间为发生器播种).只需r = System.Random()稍微移动您的声明,并在整个代码中使用该生成器.

例:

let rec cut l =
    match l with
    | [] -> // the list is empty, end the recursion here
    | head::tail -> // the list consists of the head element and the rest
                    // you can refer to head and tail in your code here
                    let newlist = r.next(100) :: tail
Run Code Online (Sandbox Code Playgroud)
  • 你在递归'cut'函数中声明了一个名为'cut'的函数,这意味着在递归函数中对'cut'的最后一次调用实际上调用了你在里面定义的非递归函数.在那里使用不同的名称

  • 你写了'如果List.length l = 0然后l',它(除了不使用模式匹配)也会出现问题:F#中的'if'是一个表达式,就像?C#中的运算符一样.在C#中,这意味着什么

    (l.Count == 0) ? l : //other case missing! error! danger!

  • 另一个提示:一旦列表被排序,每次添加新的随机元素时都不需要再次排序.您可以编写在排序列表中插入新元素的代码,该代码比添加元素和后续排序更有效.我将把insert-into-sorted-list作为练习.

我希望这些提示很有用.


Huu*_*som 0

它看起来确实像家庭作业:)但这是我的看法:

#light

// Create random integer sequence
let random_integers_of_length l  = 
    (l, new System.Random()) 
        |> Seq.unfold (fun (c, rnd) -> if c = 0 then None else Some (rnd.Next(), (c-1, rnd))) 
        |> Seq.cache

let rec mutate numbers =
    printfn "%A" (List.ofSeq numbers);                          // pretty print the list
    match numbers with                                  
    | _ when (Seq.length numbers) <= 1 -> printfn "Done.."      // if length is 1 or 0 we can stop.
    | _ ->
        numbers
            |> Seq.skip 1                                       // discard first element 
            |> Seq.append (random_integers_of_length 1)         // append random number at the start 
            |> Seq.sort                                         // sort 
            |> Seq.take ((Seq.length numbers) / 2)              // take the first half, ignore the rest
            |> Seq.skip 1                                       // discard first element 
            |> mutate                                           // do it again.
Run Code Online (Sandbox Code Playgroud)