List F中的列表操作#

List F中的列表操作#,list,recursion,f#,List,Recursion,F#,我希望这个函数能做的是: 生成由count指定长度的随机整数列表 生成另一个随机数以替换列表的第一个元素 对列表排序 将列表一分为二,丢弃下半部分 放弃列表的第一个元素 重复2-5,除非列表为空 到目前为止我所拥有的(但没有工作)如下。怎么了 let go count = let rec cut l = if List.length l = 0 then l printfn "%A" l let list = System.Random(

我希望这个函数能做的是:

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

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

  • 对列表排序

  • 将列表一分为二,丢弃下半部分

  • 放弃列表的第一个元素

  • 重复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
    

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

    #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.
    
    #灯
    //创建随机整数序列
    设长度为l的随机整数=
    (l,新系统。随机()
    |>Seq.unfold(fun(c,rnd)->如果c=0,则没有其他(rnd.Next(),(c-1,rnd)))
    |>Seq.cache
    让rec变异数字=
    printfn“%A”(序列号列表);//打印列表
    匹配数字
    |_uu当(序列长度编号)打印fn“完成”//如果长度为1或0,我们可以停止。
    | _ ->
    数字
    |>Seq.skip 1//放弃第一个元素
    |>Seq.append(长度为1的随机整数)//在开始处追加随机数
    |>Seq.sort//sort
    |>Seq.take((Seq.length number)/2)//取上半部分,忽略其余部分
    |>Seq.skip 1//放弃第一个元素
    |>变异//再做一次。
    
    一些提示:

    • 不测试列表是否为空。长度L=0。每次测试所需的时间与列表中元素的数量相同。改为使用模式匹配进行测试,这(几乎)是瞬时的:

    • 不要在每次调用
      cut
      函数时实例化随机数生成器的新实例:
      let list=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
    
    • 您在递归“cut”函数中声明了一个名为“cut”的函数,这意味着在递归函数中对“cut”的最后一次调用实际上调用了您在其中定义的非递归函数。在那里使用不同的名称

    • 您编写了“if List.length l=0 then l”,这(除了不使用模式匹配之外)还带来了一个问题:F#中的“if”是一个表达式,就像C#中的
      运算符一样。在C中,这意味着

      (l.Count==0)?l://其他案件失踪!错误!危险

    • 另一个提示:列表排序后,不需要每次添加新的随机元素时再次排序。您可以编写在排序列表中插入新元素的代码,这比添加元素并随后排序更有效。我将把插入作为练习留在排序列表中

    我希望这些提示有用。

    这是我的尝试

    let go count = 
        System.Random() |> fun rnd ->  // With ranomizer ... (we will need it)
            let rec repeat = function  // So we got recursion 
                | x::xs when xs.Length <> 1 ->       // while we have head and tail
                    printfn "%A" xs
                    rnd .Next(100) :: (List.tail xs) // Add random value
                    |> Seq.sort                      // Sort
                    |> Seq.take( abs(xs.Length /2) ) // Make a half
                    |> Seq.skip 1                    // Remove first (just skip)
                    |> List.ofSeq                    // Make the list
                    |> repeat                        // So and repeat
                | x::xs -> printfn "%A" xs
                | _ -> ()              // If we have no head and tail
            repeat <| List.init count (fun _ -> rnd.Next(100)) // do it with our random list
    
    放手计数=
    System.Random()|>fun rnd->//使用ranomizer。。。(我们需要它)
    让rec repeat=function//我们得到递归
    |x::xs when xs.Length 1->//当我们有头和尾时
    printfn“%A”xs
    rnd.Next(100):(List.tail xs)//添加随机值
    |>Seq.sort//sort
    |>Seq.take(abs(xs.Length/2))//做一半
    |>Seq.skip 1//首先删除(只需跳过)
    |>List.ofSeq//列出清单
    |>重复//So,然后重复
    |x::xs->printfn“%A”xs
    |如果我们没有头和尾巴
    重复rnd.Next(100))//使用我们的随机列表
    
    在这里,只需为每个语句生成函数即可

    let rnd = new System.Random()
    
    let genList n = 
        [for i = 0 to n-1 do yield rnd.Next()]
    
    let replaceHead v lst = match lst with
                            | [] -> []
                            | (x::xs) -> (v::xs)
    
    let splitInHalf lst = 
        let len = (lst |> List.length) / 2
        let rec loop n lst = 
            match (n,lst) with
            | 0,_ -> []
            | _,[] -> []
            | _,(x::xs) -> x :: (loop (n-1) xs)
        loop len lst
    
    
    let start n = 
        let lst = genList n
        let rec loop l = 
            match l with
            | [] -> []
            | ls -> match ls |> replaceHead (rnd.Next()) 
                             |> List.sort 
                             |> splitInHalf with
                    | [] -> []
                    | xs -> xs |> List.tail |> loop
    
        loop lst
    
    start 1
    

    我不知道F#,但在一个函数中包含太多内容似乎很明显。将任务拆分为更小的函数(更容易获得正确的函数),测试它们,然后使用它们组装go函数。这也让其他人更容易帮助你。@Landei我真的看不出制作更小的函数并一次性使用它们有什么意义。读取功能代码与读取OOP代码不同。小函数只有在被多次使用时才被使用,这在我看来是纯洁的一部分。哪个学校教F#?它是西雅图大学语言和计算课程的一部分。课程的重点不是F#,特别是这项作业。@nCdy:这不是面向对象与功能的问题:你的大脑只能专注于一定数量的数据。你能得到的一切“让开”都有助于集中精力解决真正的问题。如果你认为太多的小函数会把你的代码弄得乱七八糟,你仍然可以在以后把它们放回大函数中——但只有在它已经工作的时候。你能在第二行评论一下吗?(System.Random()|>fun rnd->)我不确定自己是否完全理解那里发生的事情。你能不能不创建“let rnd=System.Random()”?@Oldrich Svec它是一个管道+lambda(我使用System.Random()作为lambda函数的参数)是的,let rnd=System.Random()是相同的,但我的rnd只在这个lambda内工作。就我们没有其他函数而言,使用它是没有意义的,但我喜欢像sql“With”style那样使用它。另外:例如,它不能像sql那样使用IDisposable(使用@Danny yes,我的错,我认为x::xs只有在有头和尾的情况下才有效,但它甚至包含一个元素。添加了解决方法,但可能遗漏了其他内容,我不太确定。我希望在每次排序时打印列表。此语法仍然有效。)