如何将3元组的序列相加?并计算他们的平均值?

Dak*_*kaa 0 f# f#-interactive

我有一系列像这样的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)

我试过用:

你如何总结和平均序列?

3元组列表的第一个元素的总和

http://social.msdn.microsoft.com/Forums/vstudio/en-US/776d6f05-40c9-43ac-9b1c-eab188466eed/f-how-to-use-foldback-for-array-of-tuples?forum= fsharpgeneral

Tom*_*cek 8

在您的示例中,(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)