2

誰かがこれのより良いおよび/またはよりエレガントな実装を提案できますか:

各 xs =
    let rec each' acc left right =
        と正しく一致する
        | | [] -> ACC
        | | 右 -> let new_left = 左 @ [List.hd 右]
                    let next = List.tl 右
                    let result = (List.hd right), left @ next
                    each' (result::acc) new_left 次へ
    each' [] [] xs

それはそれをします:

> 各 [1..3];;
val it : (int * int list) list = [(3, [1; 2]); (2, [1; 3]); (1, [2; 3])]

この関数は、結果を逆方向に返すこともできます。アイデアは、要素と残りの要素のリストを持つタプルとしてすべての要素を取得することです。

4

5 に答える 5

7

ここではセマンティックが少し異なりますが、あなたが与えた例からはSetぴったりかもしれません:

let each xs =
    let X = set xs                           
    [ for x in xs -> (x, X - set [x]) ]


> fsi.AddPrinter( fun (x:Set<int>) -> sprintf "%A" (Set.to_list x))
> each [1..3];;
> val it : (int * Set<int>) list = [(1, [2; 3]); (2, [1; 3]); (3, [1; 2])]

// Edited as per comments.
于 2009-07-27T18:41:09.490 に答える
2

どうですか:

let rec each = function
| x :: xs -> (x,xs) :: (each xs |> List.map (fun (y,ys) -> (y,x::ys)))
| [] -> []

または、末尾再帰に相当するもの(リストを逆の順序で生成する):

let each lst =
  let rec helper acc seen = function
  | [] -> acc
  | x :: xs -> 
      helper ((x,seen)::(acc |> List.map (fun (y,ys) -> (y,x::ys)))) (x::seen) xs
  helper [] [] lst
于 2009-07-27T18:43:01.423 に答える
1
let each l = l |> List.map (fun x -> x, List.filter (fun y -> y <> x) l)

注: この関数は O(n^2) です。代わりに Seq.map と Seq.filter を使用することを検討してください。

let each l = l |> Seq.map (fun x -> x, Seq.filter (fun y -> y <> x) l)

Seq版はO(n)の性能です。

于 2009-07-27T18:06:48.093 に答える
0

Foldを使用した私の他の提案。線形関数 O(N) です。しかし、間違いなく DannyAsher のソリューションほどエレガントでシンプルではありません。

let each5 xs =  let fu (left, next, acc) x = left@[x], List.tl next, (x, left@(List.tl next))::acc
                let (x, y, res) = List.fold fu ([], xs, []) xs
                res
于 2009-07-28T10:29:53.497 に答える
0

これは、元のソリューションよりもはるかに優れているとは言えませんが、ここではそうです。このバージョンでは、ユーティリティ関数を使用して、反転した左のリストを右の末尾にマージすることにより、リストの追加を回避します。また、head 関数と tail 関数の代わりにパターン マッチングを使用します。

let rec ljoin revleft right =  
  match revleft with 
       | [] -> right 
       | (x::xs) -> ljoin xs (x::right)                                                                                   
let each xs =
    let rec each' acc left right =
       match right with
       | [] -> acc
       | (y::ys) ->
           let result = y, ljoin left ys 
           each' (result::acc) (y::left) ys
    each' [] [] xs
于 2009-07-27T18:35:13.967 に答える