4

F# では、有限の Sequence-likeseq [0; 1; 2; 3; 4]をタプルの Sequence のようなものに最適に変換するにはどうすればよいseq [4,0,1 ; 0,1,2 ; 1,2,3 ; 2,3,4 ; 3,4,0]ですか?

追加: My Seq は循環データを表します。この場合、閉じたポリラインの頂点です。各コーナーの角度を計算するには、隣接する要素が必要です。

4

7 に答える 7

3

これで正しい答えが得られます。最初に持っていた要素が最後になりましたが、それは問題ではありません。3 点のすべてのセットの角度を見つけることができます。

let cycle s =
    Seq.append s (Seq.take 2 s) // append the first two elements to the and
    |> Seq.windowed 3           // create windows of 3
    |> Seq.map (fun a -> (a.[0], a.[1], a.[2])) // create tuples


// test
[0;1;2;3;4] |> cycle

// returns:
>
  val it : seq<int * int * int> =
  seq [(0, 1, 2); (1, 2, 3); (2, 3, 4); (3, 4, 0); ...]
于 2013-06-21T18:08:46.627 に答える
3

怠惰が必要ない場合は、中間配列を使用する方が効率的かもしれません。

// get items (i-1, i, i+1) from arr; wrap around at the boundaries
let adj3 i (arr: 'a[]) =
    // modulo operator that works correctly
    let inline (%%) x y = ((x % y) + y) % y
    let len = arr.Length
    arr.[(i - 1) %% len], arr.[i], arr.[(i + 1) %% len]

let windowed3 s = seq { 
    let sarr = s |> Seq.toArray    
    for i = 0 to sarr.Length do 
        yield adj3 i sarr }

時間計算量は O( n ) です。

于 2013-06-22T20:15:32.043 に答える
3

ここにはいくつかの良い答えがありますが、ここにさらに別の答えがあります。私には、それは最も読みやすく見え、複雑さがありO(n)、またいくつかのエラーチェックを保持しています:

// Returns the last element of a sequence.
// Fails on empty sequence
let last xs =
    let len = Seq.length xs - 1
    if len < 0 then failwith "Sequence must be non-empty"
    xs
    |> Seq.skip len
    |> Seq.head

// Converts an array into a tuple
let toTuple = function
    | [|a; b; c|] -> (a, b, c)
    | _ -> failwith "Must be an array with exactly 3 elements"

let windowedBy3 xs =
    seq {
        yield last xs;
        yield! xs;
        yield Seq.head xs
    }
    |> Seq.windowed 3
    |> Seq.map toTuple

// Usage
Seq.init 5 id
|> windowedBy3
|> Seq.iter (printf "%A; ")
于 2013-06-22T03:54:04.080 に答える
2

私は次のようにします:

let neighbors xs =
  match Array.ofSeq xs with
  | [||] -> [||]
  | [|x|] -> [|x, x, x|]
  | xs ->
      let n = xs.Length
      [|yield xs.[n-1], xs.[0], xs.[1]
        for i=1 to n-2 do
          yield xs.[i-1], xs.[i], xs.[i+1]
        yield xs.[n-2], xs.[n-1], xs.[0]|]

比較は、通常、モジュロ整数演算よりもはるかに高速です。高速化するには、シーケンス式を使用する代わりに、配列を事前に割り当てて要素を埋めます。

于 2013-12-24T17:15:26.130 に答える