我有一系列像这样的3元组:
[(123, 143 ,136), (177, 284, 248), (143, 182, 252)...]
Run Code Online (Sandbox Code Playgroud)
我想通过总结所有3元组来将它们分成单个3元组:
[((x1+x2+x3),(y1+y2+y3),(z1+z2+z3))]
Run Code Online (Sandbox Code Playgroud)
然后找到他们的平均值
[((x1+x2+x3)/n,(y1+y2+y3)/n,(z1+z2+z3)/n)]
Run Code Online (Sandbox Code Playgroud)
我总结他们的尝试:
let averageRGB seqRGB = seqRGB |> Seq.fold(fun(R, G, B)(r, g, b) -> (R+r, G+g, B+b)) (0, 0, 0) (r, g, b)
Run Code Online (Sandbox Code Playgroud)
我试过用:
在您的示例中,(r, g, b)不需要最后一个表达式.没有它,您的代码会正确地对值进行求和.使用变量的大写名称并不是特别惯用,所以我将它写成:
let averageRGB seqRGB =
seqRGB |> Seq.fold (fun (r1,g1,b1) (r2,g2,b2) -> (r1+r2, g1+g2, b1+b2)) (0, 0, 0)
Run Code Online (Sandbox Code Playgroud)
要计算平均值,您只需要将结果除以元素数.您可以使用它Seq.length来获取序列的长度,但这会再次迭代序列.因此,最好将计数作为另一个参数保持在以下状态fold:
let averageRGB seqRGB =
let r,g,b,count = seqRGB |> Seq.fold (fun (r1,g1,b1,count) (r2,g2,b2) ->
(r1+r2, g1+g2, b1+b2, count+1)) (0, 0, 0, 0)
(r/count, g/count, b/count)
Run Code Online (Sandbox Code Playgroud)
请注意,这使用整数进行计算 - 因此它也会进行整数除法.如果你正在使用浮点数,你可以只改变0常量0.0,F#将推断该函数适用于浮点数.
如果您想要更高级的解决方案,那么您可以定义自己的类型来表示颜色.对于正确的类型定义,您可以使用just得到平均值Seq.average.所以,如果你想使用记录类型,你可以写:
type Color =
{ R : int; G : int; B : int }
static member (+) (c1, c2) =
{ R = c1.R + c2.R; G = c1.G + c2.G; B = c1.B + c2.B }
static member DivideByInt(c, n) =
{ R = c.R / n; G = c.G / n; B = c.B / n}
static member Zero = { R=0; G=0; B=0 }
Run Code Online (Sandbox Code Playgroud)
该记录具有重载的+运算符,Zero成员和DivideByInt方法,这使得以下可能:
[ {R=255;G=0;B=0}; {R=0;G=128;B=255} ]
|> Seq.average
Run Code Online (Sandbox Code Playgroud)