2017-05-11 19 views
5

là có một cách để làm phẳng tuples kích thước tùy ý trong F # mà không ánh xạ chúng một cách rõ ràng?F # flatten tuples lồng nhau

(fun ((((a0,a1),a2),b),c) -> (a0,a1,a2,b,c)) 

Lưu ý: Tôi nhận được các loại bộ dữ liệu này từ FParsec nhưng khả năng sẽ thuận tiện nếu có sẵn.

cảm ơn,

+4

Trong FParsec, bạn có thể sử dụng các hàm 'tuple3, tuple4, tuple5' hoặc' pipe3, pipe4, pipe5' để kết hợp nhiều trình phân tích cú pháp hơn, điều này có thể làm giảm nhu cầu của bạn về điều gì đó tương tự. – TheInnerLight

+0

@TheInnerLight điểm tuyệt vời nhờ –

Trả lời

3

Bạn không thể làm điều đó một cách dễ dàng, nhưng với một chút suy nghĩ nó có thể:

let isTuple tuple = 
    Microsoft.FSharp.Reflection.FSharpType.IsTuple(tuple.GetType()) 

let tupleValues (tuple : obj) = 
    Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields tuple |> Array.toList 

let rec flatten tupleFields = 
    tupleFields |> List.collect(fun value -> 
     match isTuple value with 
     | true -> flatten (tupleValues value) 
     | false -> [value] 
    ) 

let tupleToList (tuple : obj) = 
    if isTuple tuple 
     then Some (tupleValues tuple |> flatten) 
     else None 

Vì vậy, ví dụ:

let s = tupleToList ((100,101,102,103),1,2,3,(4,5)) 

sẽ cung cấp cho bạn :

[100; 101; 102; 103; 1; 2; 3; 4; 5] 

LƯU Ý: Câu trả lời này er được dựa trên mã được tìm thấy here.

+1

Phản ánh phải là một phương sách cuối cùng tuyệt đối mặc dù; nó thường khủng khiếp về an toàn và hiệu suất loại. Tôi sẽ làm nhiều hơn là làm những gì @ TheInnerLight nói và sử dụng các chức năng chuyên dụng của FParsec. – Tarmil

+1

@Tarmil Hoàn toàn đồng ý với bạn Tarmill - chỉ cần đưa ra cách tôi phrased câu hỏi của Sean câu trả lời là chính xác. –