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 は循環データを表します。この場合、閉じたポリラインの頂点です。各コーナーの角度を計算するには、隣接する要素が必要です。
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 は循環データを表します。この場合、閉じたポリラインの頂点です。各コーナーの角度を計算するには、隣接する要素が必要です。
これで正しい答えが得られます。最初に持っていた要素が最後になりましたが、それは問題ではありません。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); ...]
怠惰が必要ない場合は、中間配列を使用する方が効率的かもしれません。
// 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 ) です。
ここにはいくつかの良い答えがありますが、ここにさらに別の答えがあります。私には、それは最も読みやすく見え、複雑さがあり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; ")
私は次のようにします:
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]|]
比較は、通常、モジュロ整数演算よりもはるかに高速です。高速化するには、シーケンス式を使用する代わりに、配列を事前に割り当てて要素を埋めます。