2012-01-18 16 views
13

無限に繰り返す要素の部分列を含む無限列を作成する必要があります。繰り返し要素を持つ無限列

[1; 2; 3; 4; 1; 2; 3; 4; 1; 2; 3; 4; ...] 

だから私はこれを書いた:

let l = [1; 2; 3; 4] 
let s = seq { while true do yield! l } 

は、これを行うための標準的な方法(機能)はありますか?

答えて

17

私はあなたのアプローチがこのシナリオでは良いと思います。そこ繰り返しを実装するための組み込みの機能はありませんが、あなたは、多くの場合、シーケンスを繰り返す必要がある場合は、1を自分で定義し、Seqモジュールで、それを利用できるようにすることができます。

module Seq = 
    let repeat items = 
    seq { while true do yield! items } 

かのように、あなたがうまく、Seq.repeat [ 1 .. 4 ]を書くことができますF#IntelliSenseは、SeqモジュールとSeqモジュールの両方の機能を1つのモジュールで定義されているかのように表示するため、標準のF#ライブラリ関数でした(repeat)。

あなたの実装とは別に、再帰的シーケンス式を使用することもできます。これは、シーケンスを生成する際によく使用されるもう1つのパターンです。 (あなたは、単純な繰り返しのためにどのような状態を必要としませんが)whileを使用することで、機能再帰に比べていくつかの点で不可欠である:

let rec repeat items = 
    seq { yield! items 
     yield! repeat items } 

このアプローチあなたが発生しながら、いくつかの状態を維持したいときよりよいです。たとえば、1 ..のすべての数字を生成すると、whileを使用すると、可変状態が必要となるため、あまりうまくいかないでしょう。再帰を使用すると、あなたは同じことを書くことができますように:

let rec numbersFrom n = 
    seq { yield n 
     yield! numbersFrom (n + 1) } 
3

私はこれにイディオムはないと思いますが、あなたが持っているものは大丈夫ですが、ここにいくつかの選択肢があります。

アレイにあなたのサブシーケンスを変更した場合、あなたはあなたが持っているものを使用して

let a = [|1; 2; 3; 4|] 
let s = Seq.initInfinite (fun i -> a.[i % a.Length]) 

を行うことができ、あなたも

let l = [1; 2; 3; 4] 
let s = Seq.initInfinite (fun _ -> l) |> Seq.concat 

を行うことができますが、それは何の短いません。

+4

一つの落とし穴ここに: 'Seq.initInfinite'は、ある無限大の値に対して無限のシーケンスしか生成しません。 [documentation](http://msdn.microsoft.com/en-us/library/ee370429.aspx)から: "反復はInt32.MaxValueまで続けることができます。" –

+1

これは、コアlibの無限の定義に適合します。これは使用可能な作業定義です。 – Daniel

1

これは、ヘルパーオブジェクトを作成することなく、(多かれ少なかれ)1ライナーとして実行します。

let s = seq { while true do 
       for i in 1 .. 4 -> i } 
+0

[1; 2; 3; 4]リストは一例にすぎません。実際には、シーケンスを構築するために必要なオブジェクトのリストがあります。 – Max

1

ダニエルの答えに似ていますが、機能にそれをカプセル化し、その機能をふりするのSeqモジュールである:

module Seq = 
    let infiniteOf repeatedList = 
     Seq.initInfinite (fun _ -> repeatedList) 
     |> Seq.concat 

// Tests 
let intList = [1; 2; 3; 4] 
let charList = ['a'; 'b'; 'c'; 'd'] 
let objList = [(new System.Object()); (new System.Object()); (new System.Object()); (new System.Object())] 
do 
    Seq.infiniteOf intList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item) 
    Seq.infiniteOf charList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item) 
    Seq.infiniteOf objList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item) 
関連する問題