在大多数情况下,在F#中编写代码会导致非常简洁的直观工作。这段代码对我来说看起来有点迫切和不方便。
times
是一个浮点值数组文件times.csv
内的行总是这样:
Mai 06 2011 05:43:45 nachm.,00:22.99
Mai 04 2011 08:59:12 nachm.,00:22.73
Mai 04 2011 08:58:27 nachm.,00:19.38
Mai 04 2011 08:57:54 nachm.,00:18.00
average
生成值的平均值,删除最低和最高时间getAllSubsetsOfLengthN
创建一系列长度为n
的所有连续子集。是否有一个'更好'的解决方案?或者在F#核心内部已经存在类似内容?bestAverageOfN
找到所有子集的最低平均值let times =
File.ReadAllLines "times.csv"
|> Array.map (fun l -> float (l.Substring((l.LastIndexOf ':') + 1)))
let average set =
(Array.sum set - Array.min set - Array.max set) / float (set.Length - 2)
let getAllSubsetsOfLengthN n (set:float list) =
seq { for i in [0 .. set.Length - n] -> set
|> Seq.skip i
|> Seq.take n }
let bestAverageOfN n =
times
|> Array.toList
|> getAllSubsetsOfLengthN n
|> Seq.map (fun t -> t
|> Seq.toArray
|> average)
|> Seq.min
我正在寻找的是更好,更短或更简单的解决方案。当然,每个有用的帖子都会被投票赞成:)
答案 0 :(得分:4)
我猜,getAllSubsetsOfLengthN可以用Seq.windowed替换
所以bestAverageOfN看起来像:
let bestAverageOfN n =
times
|> Seq.windowed n
|> Seq.map average
|> Seq.min
答案 1 :(得分:3)
没有多想,你可以做一些基本的功能重构。例如,在bestAverageOfN
的计算中,您可以使用函数组合:
let bestAverageOfN n =
times
|> Array.toList
|> getAllSubsetsOfLengthN n
|> Seq.map (Seq.toArray >> average)
|> Seq.min
除了这个以及desco的建议之外,我认为我不会改变任何事情。如果您不在代码中的任何位置使用特殊的average
函数,则可以将其作为lambda函数内联编写,但这实际上取决于您的个人偏好。
仅仅为了一般性,我可能会times
bestAverageOfN
的论点:
let bestAverageOfN n times =
times
|> Seq.windowed n
|> Seq.map (fun set ->
(Array.sum set - Array.min set - Array.max set) / float (set.Length - 2))
|> Seq.min
答案 2 :(得分:2)
由于你提到正则表达式来解析你的输入,我想我会告诉你这样的解决方案。它可能有点矫枉过正,但它也是一个更实用的解决方案,因为正则表达式是声明性的,而子串的东西更为必要。正则表达式也很好,因为如果输入的结构发生变化,索引子字符串的内容会变得混乱,我会更容易增长,并且我会尽量避免它。
首先是几个活跃的模式,
open System.Text.RegularExpressions
let (|Groups|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then
Some([for g in m.Groups -> g.Value] |> List.tail)
else
None
open System
let (|Float|_|) input =
match Double.TryParse(input) with
| true, value -> Some(value)
| _ -> None
采用@ ildjarn的times
实施:
let times =
File.ReadAllLines "times.csv"
|> Array.map (function Groups @",.*?:(.*)$" [Float(value)] -> value)
答案 3 :(得分:1)
由于bestAversageOfN
已经涵盖,所以这是times
的替代实现:
let times =
File.ReadAllLines "times.csv"
|> Array.map (fun l -> l.LastIndexOf ':' |> (+) 1 |> l.Substring |> float)