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");...}
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");...}
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)
(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
đ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
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
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)
tuyệt vời ........ – Indy9000
Đ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 }
"Điều tra viên không phải lúc nào cũng xấu" +1 cho rằng . – AruniRC
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
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)
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)
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