18

配列let foo = [|1;2;3;4|]を使用すると、次のいずれかを使用して配列からスライスを返すことができます。

foo.[..2] 
foo.[1..2] 
foo.[2..]

リストに対して同じことを行うにはどうすればよいlet foo2 = [1;2;3;4]ですか?配列と同じ構文を試してみると、error FS00039: The field, constructor or member 'GetSlice' is not defined.

リストのサブセクションを取得するための推奨される方法は何ですか?また、GetSliceをサポートするように構築されていないのはなぜですか?

4

2 に答える 2

43

リストのサブセクションを取得するための推奨される方法は何ですか?また、GetSliceをサポートするように構築されていないのはなぜですか?

最後の質問を最初に、最初の質問を最後にしましょう。

リストがGetSliceをサポートしない理由

リストはリンクリストとして実装されているため、インデックスに効率的にアクセスすることはできません。比較的言えば、配列には時間がかかり、同等の構文はリストに時間がかかりfoo.[|m..n|]ます。これはかなり大きな問題です。なぜなら、それが役立つ場合のほとんどの場合、スライス構文を効率的に使用することができないからです。O(n-m)O(n)

たとえば、線形時間で配列を同じサイズの断片に分割できます。

let foo = [|1 .. 100|]
let size = 4
let fuz = [|for a in 0 .. size .. 100 do yield foo.[a..a+size] |]

しかし、代わりにリストを使用していた場合はどうなりますか?を呼び出すたびにfoo.[a..a+size]時間がかかり、操作全体が長くなり、O(n^2)仕事にはかなり不向きになります。

ほとんどの場合、リストをスライスすることは間違ったアプローチです。通常、パターンマッチングを使用して、リストをトラバースおよび操作します。

リストをスライスするための好ましい方法は?

可能な限り、パターンマッチングを使用してください。それ以外の場合は、フォールバックしてリストとシーケンスを切り取ることSeq.skipができます。Seq.take

> [1 .. 10] |> Seq.skip 3 |> Seq.take 5 |> Seq.toList;;
val it : int list = [4; 5; 6; 7; 8]
于 2009-12-31T08:22:30.690 に答える
10

F#4.0では、リストのスライス構文が許可されます(リンク)。

理論的根拠はここにあります:

F#リスト型はすでにインデックス演算子xs。[3]をサポートしています。これは、リストがF#のリンクリストであるという事実にもかかわらず行われます。リストはF#で非常に一般的に使用されているため、F#2.0ではこれをサポートすることが決定されました。

インデックス構文がサポートされているため、xs。[3..5]などのF#スライス構文もサポートすることは理にかなっています。スライスを使用するために配列型に切り替える必要があるのは非常に奇妙ですが、インデックス付けのためにその切り替えを行う必要はありません。

それでも、ジュリエットは、リストをスライスすることはほとんどの場合間違ったアプローチであると言って答えますが、それでも当てはまります。したがって、この機能を使用するときは賢明です。

于 2014-12-26T18:23:58.860 に答える