Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 开发一个函数,该函数接受一个整数列表,该列表定义了最长的连续相同数链_F#_Functional Programming - Fatal编程技术网

F# 开发一个函数,该函数接受一个整数列表,该列表定义了最长的连续相同数链

F# 开发一个函数,该函数接受一个整数列表,该列表定义了最长的连续相同数链,f#,functional-programming,F#,Functional Programming,请帮忙 开发一个函数,该函数接受一个整数列表,该列表定义了最长的连续相同数链。函数的结果必须是一对(数字、链的长度) 我的代码:- let findMaxSeq (nums: int list) = let foldFun (curN, len, (curWinN, curWinLen)) n = match len, curWinLen with | 0, 0 -> (n, 1, (n,1)) | 0, _ -> (n, 1, (curWinN,curWinLen)) |

请帮忙

开发一个函数,该函数接受一个整数列表,该列表定义了最长的连续相同数链。函数的结果必须是一对(数字、链的长度)

我的代码:-

let findMaxSeq (nums: int list) = 
let foldFun (curN, len, (curWinN, curWinLen)) n = 
match len, curWinLen with 
| 0, 0 -> (n, 1, (n,1)) 
| 0, _ -> (n, 1, (curWinN,curWinLen)) 
| _ when n = curN -> 
let newLen = len+1 
if (newLen>curWinLen) then (n, newLen, (n, newLen)) else (n, newLen, (curWinN, curWinLen))
| _ -> (n, 1, (curWinN, curWinLen))

let (_, _, (winner)) = nums |> List.fold foldFun (0, 0, (0, 0))
winner
但不要编译-在第二秒内让我有错误:-

此“let”后面的块未完成。期待一个表情


这可能是问题所在吗?按如下格式进行编译:

let findMaxSeq (nums: int list) = 
  let foldFun (curN, len, (curWinN, curWinLen)) n = 
    match len, curWinLen with 
    | 0, 0 -> (n, 1, (n,1)) 
    | 0, _ -> (n, 1, (curWinN,curWinLen)) 
    | _ when n = curN -> 
      let newLen = len+1 
      if (newLen>curWinLen) then (n, newLen, (n, newLen)) 
      else (n, newLen, (curWinN, curWinLen))
    | _ -> (n, 1, (curWinN, curWinLen))
  let (_, _, (winner)) = nums |> List.fold foldFun (0, 0, (0, 0))
  winner
这看起来是一个有趣的挑战,所以我尝试了一下

let findMaxRepeatedValue xs = 
  let rec loop (maxVal, maxCount) (curVal, curCount) = function
  | [] -> if curCount > maxCount then (curVal, curCount) else (maxVal, maxCount)
  | x::xs when x = curVal -> loop (maxVal, maxCount) (curVal, curCount + 1) xs
  | x::xs -> 
    if curCount > maxCount then loop (curVal, curCount) (x, 1) xs
    else loop (maxVal, maxCount) (x, 1) xs
  match xs with
  | [] -> invalidArg "xs" "empty list"
  | [x] -> (x, 1)
  | x::xs -> loop (x, 1) (x, 1) xs

既然你的主要问题已经得到了回答,这里还有另一个选择/方法,为了乐趣和利润:)


正如Daniel指出的,这只是一个缩进问题——F#是一种缩进敏感语言(空格有意义),因此需要进一步缩进嵌套块。当函数正确缩进时,它可以正常工作

let findMaxSeq (nums: int list) = 
  let foldFun (curN, len, (curWinN, curWinLen)) n = 
    match len, curWinLen with 
    | 0, 0 -> (n, 1, (n,1)) 
    | 0, _ -> (n, 1, (curWinN,curWinLen)) 
    | _ when n = curN -> 
       let newLen = len+1 
       if (newLen>curWinLen) then 
         (n, newLen, (n, newLen)) 
       else 
         (n, newLen, (curWinN, curWinLen))
    | _ -> (n, 1, (curWinN, curWinLen))

  let (_, _, (winner)) = nums |> List.fold foldFun (0, 0, (0, 0))
  winner

findMaxSeq [1;2;2;2;3;3;1;1;1;1;1;4;4]
请注意:

  • 函数体
    foldFun
    比定义函数的
    let
    缩进得更远
  • 复合图案的主体(当
    n=curN
    时匹配)也进一步缩进
  • 我还将
    拆分为多行(为了可读性-这不是必需的)
Daniel的解决方案也很好——但既然您询问了一个基于
List.fold
的版本,我想我应该用您原始代码的更正版本来回答

另一方面,如果您想对一些实际数据(如时间序列)执行更多类似这样的操作,而不是为了学习F#而解决这个问题,那么这是一个用于处理序列数据的库,它有一个很好的抽象,称为
chunkWhile
,它在某些条件成立时将序列拆分为块(例如,虽然值相同)并使编写以下内容变得非常简单:

#r "lib/Deedle.dll"
open Deedle

let findMaxSeq values = 
  let s = Series.ofValues values
  s |> Series.chunkWhile (fun k1 k2 -> s.[k1] = s.[k2])
    |> Series.map(fun k chunk -> s.[k], Series.countKeys chunk)
    |> Series.values
    |> Seq.maxBy snd

findMaxSeq [1;2;2;2;3;3;1;1;1;1;1;4;4]
抱歉,但迄今为止我见过的大多数F#代码在我看来都像是伪装的C。我相信函数式F#程序员可以做得更好,按照Haskell的解决方案:

maxrv = maximumBy (comparing fst) . map (\xs -> (length xs, xs)) . group

这里有一个尝试,它是通用的,并且使用标准的库函数。由于您没有说明当输入序列为空时答案应该是什么,所以我不会直接返回一对
number*length
,而是将其包含在一个选项中

let inline findMaxSeq xs =
    xs 
    |> Seq.scan (fun state x ->
        match state with
        | Some (y, i) when x = y -> Some (x, i + 1)
        | _ -> Some (x, 1) )
        None
    |> Seq.maxBy (function
        | Some (_, i) -> i 
        | _ -> 0 )

findMaxSeq [1;2;2;2;3;3;1;1;1;1;1;4;4] // Some (1, 5)
findMaxSeq Seq.empty<int>              // None
让内联findMaxSeq xs=
xs
|>序列扫描(乐趣状态x->
匹配状态
|当x=y时的一些(y,i)->一些(x,i+1)
|一些(x,1))
没有一个
|>Seq.maxBy(函数
|一些(u,i)->i
| _ -> 0 )
findMaxSeq[1;2;2;3;3;1;1;1;1;1;4;4]//一些(1,5)
findMaxSeq Seq.empty//None

-1很好的一点,但很抱歉,这可以作为一个注释吗?F#没有Haskell那样的
功能,但一旦你编写了一个,你就可以产生一个几乎与你自己的解决方案完全一样的解决方案()@Daniel似乎是
系列。chunkWhile
是类似的,请参见@Thomas Petricek.Yep.的答案。看起来很相似。这是他写的一个名为Deedle的图书馆。
let inline findMaxSeq xs =
    xs 
    |> Seq.scan (fun state x ->
        match state with
        | Some (y, i) when x = y -> Some (x, i + 1)
        | _ -> Some (x, 1) )
        None
    |> Seq.maxBy (function
        | Some (_, i) -> i 
        | _ -> 0 )

findMaxSeq [1;2;2;2;3;3;1;1;1;1;1;4;4] // Some (1, 5)
findMaxSeq Seq.empty<int>              // None