2012-01-18 66 views
13

Tôi cần tạo một chuỗi vô hạn chứa một chuỗi các phần tử lặp lại vô hạn.Trình tự vô hạn với các phần tử lặp lại

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

Vì vậy, tôi đã viết này:

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

Có một cách tiêu chuẩn (chức năng) để làm điều này?

Trả lời

17

Tôi nghĩ rằng cách tiếp cận của bạn là tốt trong trường hợp này. Không có chức năng built-in để thực hiện lặp đi lặp lại, nhưng nếu bạn cần lặp lại trình tự thông thường, bạn có thể xác định một mình và làm cho nó có sẵn trong Seq mô-đun:

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

Sau đó, bạn độc đáo có thể viết Seq.repeat [ 1 .. 4 ], như thể repeat là chức năng thư viện chuẩn F #, vì F # IntelliSense hiển thị cả hai hàm từ mô-đun Seq của bạn và từ mô-đun Seq như thể chúng được xác định trong một mô-đun duy nhất.

Ngoài việc triển khai, bạn cũng có thể sử dụng biểu thức trình tự đệ quy, đó là một mẫu khá phổ biến khác khi tạo chuỗi. Sử dụng while là trong một số cách bắt buộc (mặc dù bạn không cần bất cứ tiểu bang cho lần lặp lại đơn giản) so với đệ quy chức năng:

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

Cách tiếp cận này là tốt hơn khi bạn muốn giữ lại một số trạng thái trong khi tạo ra. Ví dụ: tạo tất cả các số 1 .. bằng cách sử dụng while sẽ không đẹp như vậy, vì bạn cần trạng thái có thể thay đổi. Sử dụng đệ quy, bạn có thể viết những điều tương tự như:

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

Tôi không nghĩ rằng có một thành ngữ cho điều này, và những gì bạn có là tốt, nhưng đây là một số lựa chọn thay thế.

Nếu bạn thay đổi dãy của bạn đến một mảng, bạn có thể làm

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

Sử dụng những gì bạn có, bạn cũng có thể làm

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

nhưng nó không ngắn hơn.

+4

Một Gotcha ở đây: 'Seq.initInfinite' chỉ tạo ra các chuỗi vô hạn cho các giá trị vô hạn nhất định. Từ [tài liệu] (http://msdn.microsoft.com/en-us/library/ee370429.aspx): "Lặp lại có thể tiếp tục tới Int32.MaxValue." –

+1

Nó phù hợp với định nghĩa cốt lõi của lib về vô hạn, đó là một định nghĩa làm việc có thể sử dụng. – Daniel

1

Điều này sẽ làm điều đó như là một (nhiều hơn hoặc ít hơn) một lớp lót, mà không cần phải tạo ra bất kỳ đối tượng trợ giúp.

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

Danh sách [1; 2; 3; 4] chỉ là một ví dụ. Trong thực tế, tôi có một danh sách các đối tượng mà tôi cần để xây dựng chuỗi từ. – Max

1

Tương tự như câu trả lời của Daniel, nhưng đóng gói nó vào một chức năng, và giả vờ chức năng đó là trong module 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) 
Các vấn đề liên quan