如何从 F# Seq 获取连续值对

发布于 2024-10-01 01:08:35 字数 128 浏览 0 评论 0原文

我有一个带有 {"1";"a";"2";"b";"3";"c";...} 的序列。

如何将此序列转换为 {("1","a");("2","b");("3","c");...}

I have a sequence with {"1";"a";"2";"b";"3";"c";...}.

How can I transform this seq into {("1","a");("2","b");("3","c");...}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

毁我热情 2024-10-08 01:08:35

这是一个非常聪明的解决方案:

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)

Here is a much-too-clever solution:

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)
各自安好 2024-10-08 01:08:35

枚举器并不总是邪恶的。

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

以下是来自 FSharp.Core/seq.fsSeq.pairwise 的 F# 源代码

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

Enumerators are not always evil.

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

Here is the F# source code of Seq.pairwise taken from 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 }
画骨成沙 2024-10-08 01:08:35

从 F# 4.0 开始,您现在可以使用 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)

Since F# 4.0, you can now use 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)
烈酒灼喉 2024-10-08 01:08:35

这是 @Brian 解决方案的一个变体:

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

这是一个使用 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

Here's a variation on @Brian's solution:

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

And here's a brain-melter using 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
夜未央樱花落 2024-10-08 01:08:35

您可以考虑使用 LazyLists 来实现此目的。

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)

You might consider using LazyLists for this.

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)
小…红帽 2024-10-08 01:08:35

您可以按以下方式使用模式匹配:

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

但是您必须决定如果列表有奇数个元素该怎么办(在我的解决方案中生成了一对具有相同值的元素)

You can use pattern matching in the following way:

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

but you have to decide what to do if the list has an odd number of elements (in my solution a pair with same value is produced)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文