12
votes

Comment obtenir des paires de valeurs consécutives de F # SEQ

J'ai une séquence avec {"1"; "A"; "2"; "B"; "3"; "C"; ...} .

Comment puis-je transformer ce SEQ en {("1", "A"); ("2", "B"); ...}


1 commentaires

Voici une réponse connexe qui pourrait vous intéresser: Stackoverflow.com/Questions/ 833180 / Handy-F-Snippets / ... , bien que ce soit pour les listes, pas SEQ.


6 Réponses :


0
votes

Vous pouvez utiliser le motif correspondant de la manière suivante: xxx

mais vous devez décider quoi faire si la liste a un nombre impair d'éléments (dans ma solution une paire avec la même valeur est produit)


5 commentaires

(Je ne sais pas s'il y a des constructions intelligentes dans F #, je suis habitué à OCAML :)


Cela fonctionnerait si c'était une liste mais j'ai un très grand SEQ. Je ne sais pas si cette approche correspondante de modèle fonctionnera sur un SEQ


Pourquoi ne devrait-il pas marcher? Il passe par la liste une construction la nouvelle en concaténant. Il devrait être une complexité linéaire. Ou vous êtes inquiet du débordement de pile?


Oh tu veux dire que tu veux le garder paresseux?


@Functional: Voici le même code, mais utilise la continuation qui passe pour la rendre sur la queue-recrossif Pastebin.com/vtkqgi8k



20
votes

Voici une solution beaucoup trop intelligente: xxx


0 commentaires

11
votes

Les énumérateurs ne sont pas toujours pervers.

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


1 commentaires

"Les énumérateurs ne sont pas toujours pervers" +1 à cela.



1
votes

Voici une variante de la solution de @ Brian: xxx pré>

et voici un fondoir cerveau à l'aide de SEQ.SCAN: P>

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


0 commentaires

2
votes

Vous pouvez envisager d'utiliser des lazylistes pour cela.

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)


0 commentaires

7
votes

Depuis F # 4.0, vous pouvez maintenant utiliser 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)


1 commentaires

Cela fait le tour pour moi! Mais nous devrions envisager d'utiliser le SEQ.tryItem pour récupérer les valeurs indexées. Cela pourrait vous lancer une exception si la liste source a un nombre impair de valeurs.