将列表上的函数应用于每个其他列表成员

时间:2016-04-22 20:38:58

标签: f#

假设我有一个起始列表

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.reduceList.fold也不会这样做,因为它们都是累加器而不是单独的函数。

有没有办法做我想做的事情?

感谢您的帮助

3 个答案:

答案 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])] *)