假设我有一个起始列表
let test = [1; 2; 3; 4; 5]
我希望将第一个元素添加到所有其他元素,然后将第二个元素添加到所有其他元素,依此类推,直到我最终得到类似
的内容result = [1, [3; 4; 5; 6];
2, [3; 5; 6; 7];
3, [4; 5; 7; 8];
4, [5; 6; 7; 9];
5, [6; 7; 8; 9]]
对于我的生活,我无法弄清楚哪种List.n
方法在这里是合适的,甚至是否存在。我知道List.map
不会这样做,我认为List.reduce
或List.fold
也不会这样做,因为它们都是累加器而不是单独的函数。
有没有办法做我想做的事情?
感谢您的帮助
答案 0 :(得分:7)
我认为List
模块中没有直接功能可以轻松使用,但有一个功能可以随时使用,您可以轻松定义自己:
let rec pick xs =
match xs with
| [] -> []
| (x::xs) -> (x,xs) :: (List.map (fun (x',xs') -> (x',x::xs')) (pick xs))
这个会生成元组,第一个组件是列表中的一个值,第二个组件是列表左边的组件:
pick [1..5] =
[(1, [2; 3; 4; 5])
;(2, [1; 3; 4; 5])
;(3, [1; 2; 4; 5])
;(4, [1; 2; 3; 5])
;(5, [1; 2; 3; 4])]
有了这个并不难做到你想做的事情:
let f xs =
List.map (fun (x,xs) -> (x, List.map (fun y -> y+x) xs))
(pick xs)
> f [1;2;3;4;5];;
[(1, [3; 4; 5; 6])
;(2, [3; 5; 6; 7])
;(3, [4; 5; 7; 8])
;(4, [5; 6; 7; 9])
;(5, [6; 7; 8; 9])]
答案 1 :(得分:3)
有很多方法可以做到这一点。除了卡斯滕之外,这是另一种方法。效率稍低,但在某些情况下可能有用。
首先,定义只删除列表第n个元素的有用函数withoutNth
let rec withoutNth nth list =
match (nth,list) with
| _,[] -> []
| 0,(x::xs) -> xs
| _,(x::xs) -> x::(withoutNth (nth-1) xs)
测试一下:
withoutNth 0 [1..5] // [2; 3; 4; 5]
withoutNth 1 [1..5] // [1; 3; 4; 5]
withoutNth 4 [1..5] // [1; 2; 3; 4]
有了这个,我们可以创建一个addToSiblings
函数来完成你想做的事情:
let addToSiblings list =
// helper function
let addNthToSiblings nth x =
let addX y = x + y
let newList = withoutNth nth list |> List.map addX
x,newList
// apply helper function to each element
list |> List.mapi addNthToSiblings
测试一下:
[1..5] |> addToSiblings
//[(1, [3; 4; 5; 6]);
// (2, [3; 5; 6; 7]);
// (3, [4; 5; 7; 8]);
// (4, [5; 6; 7; 9]);
// (5, [6; 7; 8; 9])]
答案 2 :(得分:0)
具有尾递归函数的变体在前置到累加器时需要反转列表。该函数可以使用continuation,而不是反转,可以按任何顺序组合。
这是一个示例,其中外部循环在向内部提供拆分输入列表后反转。内部循环使用延续来处理左侧子列表中的元素在一个方向上,而右侧的元素在另一个方向上。
let applyEachToEveryOther f =
let rec aux2 k = function
| [], _, [] -> k []
| [], x, r::rs -> aux2 (k << fun ys -> f x r::ys) ([], x, rs)
| l::ls, x, rs -> aux2 (k >> fun ys -> f x l::ys) (ls, x, rs)
let rec aux ls acc = function
| [] -> List.rev acc
| x::xs -> aux (x::ls) ((x, aux2 id (ls, x, xs))::acc) xs
aux [] []
applyEachToEveryOther (+) [1..5]
(* [(1, [3; 4; 5; 6]);
(2, [3; 5; 6; 7]);
(3, [4; 5; 7; 8]);
(4, [5; 6; 7; 9]);
(5, [6; 7; 8; 9])] *)