我希望写一些可以复制列表中所有元素的东西。所以如果我想要2个列表
[1; 2; 3; 4]
它会变成
[1; 1; 2; 2; 3; 3; 4; 4]
所以我打算用
递归写一个函数let rec dupeElem row count =
match row with
| [] -> []
| hd::tl -> (makeCopy hd count) @ dupeElem tl count
其中count是我想要的副本数。该函数将获取列表中的每个头元素并将其发送到复制功能,以使副本插入到列表中。然后makeCopy看起来像:
let makeCopy elem Count =
match Count with
| 0 -> []
| 1 -> elem
| 2 -> elem :: elem
|....
但是当它返回dupeElem时我会收到错误。我知道做难事并不是最明智的想法,而是测试它是否可行。我如何修复/改进我的工作?
答案 0 :(得分:7)
仅仅是为了非递归解决方案:
let xs = [1; 2; 3; 4; 5]
xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 1; 2; 2; 2; 3; 3; 3; 4; 4; 4; 5; 5; 5]
答案 1 :(得分:3)
makeCopy
返回0
案例的列表,但对于1
案例,您返回的是单个元素。将1
的大小写更改为以下内容应该可以修复编译时错误:
| 1 -> [elem]
对于案例2
,您对::
的使用无效,因为右侧不是列表,但它是单个元素。请考虑将其替换为以下任一项:
| 2 -> elem :: [elem]
或者...
| 2 -> [ elem; elem ]
答案 2 :(得分:2)
相互递归的方式:
let rec dupl n = function
| [] -> []
| h::t -> cons h (dupl n t) n
and cons h t = function
| 0 -> t
| n -> cons h (h::t) (n-1)
答案 3 :(得分:0)
s952163
的回答简洁明了。为了更加通用,如果您不想复制,可以定义函数f,g和h,并执行以下操作:
let xs = [1; 2; 3; 4]
let f = id // No need for type annotation, given the definitions of g and h
let g x = x * x
let h x = x * x * x
(List.zip3 xs xs xs) |> List.map (fun (a, b, c) -> [f a; g b; h c]) |> List.concat
对于您只想复制的特定情况,您可以执行
let f = id<int> // The type annotation is necessary
并且类似地对于g和h或者仅对所有三种情况使用f。当然,在这种情况下,s952163
提出的解决方案更受欢迎。