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");...}
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");...}
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)
(Nie wiem, czy istnieją sprytne konstrukcje w F #, jestem przyzwyczajony do OCaml :) – Jack
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
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
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)
sublime ........ – Indy9000
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 }
"Enumeratorzy nie zawsze są źli" +1 do tego . – AruniRC
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
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)
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)
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