2013-04-02 13 views
7

mam 'sprężonego strumienia powoduje wartości, do którego jest dołączony liczby występowania tej wartości, na przykład:powtarzalne sekwencje F #

let a = [(),1;(),4;(),3;] 

POLUBIŁEM „uncompress” tej sekwencji i emitują oryginalna sekwencja. Mogę zdefiniować kombinator powtórzeń, aby uzyskać plon! w tym celu:

let rec repeat avalue n = seq { if n > 0 then 
            yield avalue; yield! repeat avalue (n-1) } 

let b = seq { for v,n in a do 
       yield! repeat v n } |> Seq.toList 

Czy istnieje sposób wyrażenia tego w formie, w formie kompozycji?

let c = a |> Seq.XXX(fun e -> ...) 

Odpowiedz

6

Można to zrobić za pomocą Enumerable.Repeat:

> Seq.collect Enumerable.Repeat [ 1, 2; 3, 4; 5, 6 ] |> List.ofSeq;; 
val it : int list = [1; 1; 3; 3; 3; 3; 5; 5; 5; 5; 5; 5] 
+0

ah, nie wiedziałem, że jeden! – nicolas

+1

Więc ten jest najlepszy dla krotek, co jest kontekstem mojego pytania. Dlatego jest to najbardziej funkcjonalna odpowiedź. – nicolas

+2

Istnieje również ['List.replicate <'T>'] (https://msdn.microsoft.com/en-us/library/ee353665.aspx). –

3

Jak o

let c = a |> Seq.collect (fun (v,i) -> [1..i] |> Seq.map (fun x -> v)) 

nie wiem funkcję biblioteki podobną do Enumerable.Repeat; jeśli ktoś o tym wie, dodaj komentarz.

EDIT

Znalazłem podobną do funkcji biblioteki Enumerable.Repeat, choć jest w module List:

let c = a |> Seq.collect (fun (v,i) -> List.replicate i v) 

byłoby to bardziej elegancko, jeśli par w źródle sekwencja została odwrócona:

let c = a |> Seq.collect ((<||) List.replicate) 

Wygląda na to, że Enumerable.Re brunatny (jak w przyjętym odpowiedzi) rzeczywiście robi najlepsze rozwiązanie, ponieważ jego tupled argumentem dopasowuje elementy kolejności:

let c = a |> Seq.collect Enumerable.Repeat 

Jeśli ktoś wie o podobnie eleganckie rozwiązanie, które pozostaje w F # biblioteki, należy dodać komentarz ; dzięki.

+0

Miło, nie wiedziałem, że istnieje funkcja F # ('<||') podobna do 'nieśmiertelności 'Haskella! – MisterMetaphor

3
let rec repeat (item,n) = seq { if n > 0 then yield item; yield! repeat(item, n-1)} 
a |> Seq.collect repeat 

Na przykład

[('a',2); ('b',2)] |> Seq.collect repeat 

val it: seq<char> = seq ['a';'a';'b';'b'] 
+0

ładny. chociaż jest |> Seq.collect (fun (pozycja, n) -> powtórz pozycję n) – nicolas

+1

Moja wersja z krotką argumentem 'repeat' pozwala pozbyć się lambda w kombinatorze. –

Powiązane problemy