2010-11-08 40 views
6

Tôi có một chuỗi với {"1";"a";"2";"b";"3";"c";...}.cách nhận cặp giá trị liên tiếp từ F # Seq

Làm thế nào tôi có thể chuyển đổi seq này vào {("1","a");("2","b");("3","c");...}

+0

Dưới đây là một câu trả lời có liên quan mà có thể bạn quan tâm: http://stackoverflow.com/questions/833180/handy-f-snippets/2271132 # 2271132, mặc dù nó dành cho các danh sách chứ không phải Seq. – Benjol

Trả lời

0

Bạn có thể sử dụng mô hình kết hợp theo cách sau:

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 

nhưng bạn phải quyết định phải làm gì nếu danh sách có một số lẻ của các yếu tố (trong dung dịch của tôi một cặp với cùng một giá trị được sản xuất)

+0

(Tôi không biết nếu có cấu trúc thông minh trong F #, tôi đang sử dụng để OCaml :) – Jack

+0

điều này sẽ làm việc nếu nó là một danh sách nhưng tôi có một seq rất lớn. không chắc chắn nếu phương pháp này phù hợp với mô hình sẽ làm việc trên một Seq – functional

+0

tại sao nó không hoạt động? Nó đi qua danh sách xây dựng một cái mới bằng cách nối. Nó phải là phức tạp tuyến tính .. hoặc bạn đang lo lắng về tràn ngăn xếp? – Jack

15

Dưới đây là một giải pháp nhiều-quá-minh:

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

tuyệt vời ........ – Indy9000

10

ĐTV không phải lúc nào cũng xấu xa.

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) 
    } 

Dưới đây là F # mã nguồn Seq.pairwise lấy từ 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

"Điều tra viên không phải lúc nào cũng xấu" +1 cho rằng . – AruniRC

0

Dưới đây là một biến thể của @ Brian của giải pháp:

["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 

Và đây là một bộ não-melter sử dụng 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

Bạn có thể xem xét sử dụng LazyLists cho việc này.

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

Kể từ F # 4.0, bây giờ bạn có thể sử dụng 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) 
Các vấn đề liên quan