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(
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只有在有头和尾的情况下才有效,但它甚至包含一个元素。添加了解决方法,但可能遗漏了其他内容,我不太确定。我希望在每次排序时打印列表。此语法仍然有效。)