2012-01-18 19 views
13

Sonsuz tekrarlayan elemanların bir alt dizisini içeren sonsuz bir sıra oluşturmam gerekiyor.Yinelenen elemanlara sahip sonsuz dizisi

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

Bunu yapmak için standart bir yol (fonksiyonu) var mı:

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

Yani yazdı?

cevap

17

Bu senaryoda yaklaşımınızın iyi olduğunu düşünüyorum. Orada tekrarını uygulamak için yerleşik bir işlevdir, ancak genellikle dizileri tekrarlamak gerekirse, bir kendini tanımlayabilir ve Seq modülünde o kullanılabilir yapabilirsiniz: sanki

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

Sonra güzelce Seq.repeat [ 1 .. 4 ] yazabilir F # IntelliSense her iki işlevi Seq modülünden ve Seq modülünden tek bir modülde tanımlanmış gibi gösterdiğinden, repeat standart bir F # kitaplığı işleviydi.

Uygulamanızın yanı sıra, dizi oluştururken başka bir oldukça yaygın model olan yinelemeli sıra ifadesini de kullanabilirsiniz. while kullanma fonksiyonel özyineleme karşılaştırıldığında (basit tekrarlar için herhangi bir devlete ihtiyacımız yok rağmen) zorunludur bazı bakımlardan şudur: oluşturulurken bazı devlet tutmak istediğinizde

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

Bu yaklaşım daha iyidir. Örneğin, while kullanarak tüm sayıları 1 .. oluşturmak çok hoş olmaz, çünkü değiştirilebilen duruma ihtiyacınız vardır. Özyinelemeyi kullanarak, aynı şeyi yazabilirsiniz olarak:

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

Bunun için bir deyim olduğunu ve sahip olduğunuz şeyin iyi olduğunu sanmıyorum, ama burada bazı alternatifler var. Eğer bir diziye sizin altdizisi değiştirirseniz, ne varsa kullanarak

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

yapabilirsiniz

, ayrıca

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

yapabilirdi ama hiç kısa.

+4

Bir yakaladım burada: Seq.initInfinite sadece belirli sonsuzluk değerleri için sonsuz diziler üretir. [Belgeler] 'den (http://msdn.microsoft.com/en-us/library/ee370429.aspx): "İterasyon Int32.MaxValue'ye kadar devam edebilir." –

+1

Çekirdek lib'in sınırsız tanımına uyuyor, bu da kullanılabilir bir çalışma tanımı. – Daniel

1

Bu, herhangi bir yardımcı nesne oluşturmaya gerek kalmadan bir (daha fazla veya daha az) tek astar olarak yapacaktır.

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

[1; 2; 3; 4] listesi sadece bir örnekti. Gerçekte, dizi oluşturmam gereken bir nesne listesi var. – Max

1

Daniel'in cevabı benzer ancak bir fonksiyonu haline enkapsüle ve bu işlevi gibi davranarak Seq modülünde ise:

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) 
İlgili konular