折叠还是选择直到无? [英] fold or choose till None?

查看:59
本文介绍了折叠还是选择直到无?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否已经有一种方法可以执行chooseTillfoldTill之类的操作,直到接收到无"选项为止?实际上,任何高阶函数都具有耕种"选项.当然,对于地图之类的东西来说这毫无意义,但是我发现我经常需要这种东西,并且我想确保自己没有重新发明轮子.

Is there already a way to do something like a chooseTill or a foldTill, where it will process until a None option is received? Really, any of the higher order functions with a "till" option. Granted, it makes no sense for stuff like map, but I find I need this kind of thing pretty often and I wanted to make sure I wasn't reinventing the wheel.

通常,编写这样的内容很容易,但是我很好奇是否已经有一种方法可以做到这一点,或者是否存在于某个已知的库中?

In general, it'd be pretty easy to write something like this, but I'm curious if there is already a way to do this, or if this exists in some known library?

let chooseTill predicate (sequence:seq<'a>) = 
    seq {
            let finished = ref false                            
            for elem in sequence do
                if not !finished then
                    match predicate elem with
                        | Some(x) -> yield x 
                        | None -> finished := true
    }

let foldTill predicate seed list = 
    let rec foldTill' acc = function
        | [] -> acc
        | (h::t) -> match predicate acc h with 
                        | Some(x) -> foldTill' x t
                        | None -> acc
    foldTill' seed list

let (++) a b = a.ToString() + b.ToString()

let abcdef =  foldTill (fun acc v -> 
                        if Char.IsWhiteSpace v then None 
                        else Some(acc ++ v)) "" ("abcdef ghi"  |> Seq.toList)

// result is "abcdef"

推荐答案

我认为您可以通过组合Seq.scanSeq.takeWhile轻松实现这一点:

I think you can get that easily by combining Seq.scan and Seq.takeWhile:

open System

"abcdef ghi"
|> Seq.scan (fun (_, state) c -> c, (string c) + state) ('x', "")
|> Seq.takeWhile (fst >> Char.IsWhiteSpace >> not)
|> Seq.last |> snd

这个想法是Seq.scan做的事情与Seq.fold类似,但是它不等待最终结果,而是随其产生中间状态.然后,您可以继续采取中间状态,直到到达终点为止.在上面的示例中,状态是当前字符和连接的字符串(以便我们可以检查字符是否为空白).

The idea is that Seq.scan is doing something like Seq.fold, but instead of waiting for the final result, it yields the intermediate states as it goes. You can then keep taking the intermediate states until you reach the end. In the above example, the state is the current character and the concatenated string (so that we can check if the character was whitespace).

基于返回option的函数的更通用的版本可能看起来像这样:

A more general version based on a function that returns option could look like this:

let foldWhile f initial input =
  // Generate sequence of all intermediate states
  input |> Seq.scan (fun stateOpt inp -> 
       // If the current state is not 'None', then calculate a new one
       // if 'f' returns 'None' then the overall result will be 'None'
       stateOpt |> Option.bind (fun state -> f state inp)) (Some initial)
  // Take only 'Some' states and get the last one
  |> Seq.takeWhile Option.isSome
  |> Seq.last |> Option.get

这篇关于折叠还是选择直到无?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆