2010-11-08 11 views
6

Mam sekwencję z {"1";"a";"2";"b";"3";"c";...}.jak uzyskać pary kolejnych wartości z F # Seq

Jak mogę przekształcić ten nast do {("1","a");("2","b");("3","c");...}

+0

Oto odpowiedź pokrewnych, które mogą Cię interesować: http://stackoverflow.com/questions/833180/handy-f-snippets/2271132 # 2271132, choć dotyczy list, a nie Seq. – Benjol

Odpowiedz

0

można użyć dopasowywania wzorców w następujący sposób:

let list = ["1";"2";"3";"4";"5";"6"] 

let rec convert l = 
    match l with 
     x :: y :: z -> (x,y) :: convert z 
     | x :: z -> (x,x) :: convert z 
     | [] -> [] 

let _ = 
    convert list 

ale trzeba zdecydować, co zrobić, jeśli lista zawiera nieparzystą liczbę elementów (w moim roztworu parę z samej wartości jest produkowany)

+0

(Nie wiem, czy istnieją sprytne konstrukcje w F #, jestem przyzwyczajony do OCaml :) – Jack

+0

to by działało, gdyby była to lista, ale mam bardzo duże seq. nie wiesz, czy to podejście dopasowywania wzorców będzie działało na Seq – functional

+0

dlaczego nie powinno działać? Przegląda listę i buduje nową, łącząc. Powinien być złożony liniowo .. lub martwisz się przepełnieniem stosu? – Jack

15

Tutaj jest dużo było zbyt mądre rozwiązanie:

let s = ["1";"a";"2";"b";"3";"c"] 

let pairs s = 
    s |> Seq.pairwise 
     |> Seq.mapi (fun i x -> i%2=0, x) 
     |> Seq.filter fst 
     |> Seq.map snd 

printfn "%A" (pairs s) 
+0

sublime ........ – Indy9000

10

Wyliczacze nie zawsze są źli.

let pairs (source: seq<_>) = 
    seq { 
     use iter = source.GetEnumerator() 
     while iter.MoveNext() do 
      let first = iter.Current 
      if iter.MoveNext() then 
       let second = iter.Current 
       yield (first, second) 
    } 

Oto kod # source F Seq.pairwise zaczerpnięte z FSharp.Core/seq.fs

[<CompiledName("Pairwise")>] 
let pairwise (source: seq<'T>) = //' 
    checkNonNull "source" source 
    seq { use ie = source.GetEnumerator() 
      if ie.MoveNext() then 
       let iref = ref ie.Current 
       while ie.MoveNext() do 
        let j = ie.Current 
        yield (!iref, j) 
        iref := j } 
+0

"Enumeratorzy nie zawsze są źli" +1 do tego . – AruniRC

0

Oto wariacja na temat @ Briana rozwiązania:

["1";"a";"2";"b";"3";"c";"4";"d";"5";"e";"6";"f"] 
|> Seq.pairwise 
|> Seq.mapi (fun i x -> if i%2=0 then Some(x) else None) 
|> Seq.choose id 

A oto mózgu topiące użyciu Seq.scan :

["1";"a";"2";"b";"3";"c";"4";"d";"5";"e";"6";"f"] 
|> Seq.scan (fun ((i,prev),_) n -> match prev with 
            | Some(n') when i%2=0 -> ((i+1,Some(n)), Some(n',n)) 
            | _ -> ((i+1,Some(n)), None)) 
      ((-1,None), None) 
|> Seq.choose snd 
1

Możesz rozważyć użycie LazyLists do tego.

let (|Cons|Nil|) = LazyList.(|Cons|Nil|) 

let paired items = 
    let step = function 
     | Cons(x, Cons(y, rest)) -> 
      Some((x, y), rest) 
     | _ -> 
      None 
    Seq.unfold step (LazyList.ofSeq items) 
2

Ponieważ F # 4.0, można teraz używać chunkBySize

let source = seq ["1";"a";"2";"b";"3";"c"] 

let pairs source = 
    source 
    |> Seq.chunkBySize 2 
    |> Seq.map (fun a -> a.[0], a.[1]) 

;; 
printfn "%A" (pairs source) 
Powiązane problemy