请帮忙。
开发一个函数,该函数采用整数列表,将整数列表定义为相同数字的最长连续链。函数的结果必须是一对(数字,链的长度)
我的代码: -
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'未完成。期待一个表达。
答案 0 :(得分:3)
缩进是不是问题?它按以下格式编译:
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
答案 1 :(得分:3)
由于您的主要问题已得到解答,这里是另一种选择/方法,以获得乐趣和利润:)
let longestChain nums =
let rec chain lst (num, cnt) = seq {
match lst with
| x :: xs -> if x = num then
yield! chain xs (num, cnt+1)
else
yield (num, cnt)
yield! chain xs (x, 1)
| [] -> yield (num, cnt)
}
match nums with
| x :: xs -> chain xs (x, 1) |> Seq.maxBy snd
| [] -> failwith "Cannot find the longest chain in an empty list"
答案 2 :(得分:2)
正如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
时匹配)也进一步缩进if
then
拆分为多行(为了便于阅读 - 这不是必需的) Daniel的解决方案也非常好 - 但是由于您询问了基于List.fold
的版本,我想我会回复您原始代码的更正版本。
顺便说一句,如果你想在一些实际数据(如时间序列)上做更多这样的操作,而不是仅仅为了学习F#而解决这个问题,那么Deedle这是一个用于处理的库系列数据有一个很好的抽象,称为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]
答案 3 :(得分:1)
这是一种通用的尝试并使用标准库函数。由于当输入序列为空时你没有说出答案应该是什么,我不是直接返回一对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
答案 4 :(得分:-2)
很抱歉,但到目前为止,我见过她的大多数F#代码看起来都像C#一样伪装。我确信功能 F#程序员可以按照这个Haskell解决方案做得更好:
maxrv = maximumBy (comparing fst) . map (\xs -> (length xs, xs)) . group