我有一系列像这样的3元组:
[(123, 143 ,136), (177, 284, 248), (143, 182, 252)...]
我想通过总结所有3元组来将它们变成单个3元组:
[((x1+x2+x3),(y1+y2+y3),(z1+z2+z3))]
然后找到他们的平均值
[((x1+x2+x3)/n,(y1+y2+y3)/n,(z1+z2+z3)/n)]
我尝试总结它们:
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)
我尝试使用:
How do you sum up and average a Sequence?
答案 0 :(得分: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)
要计算平均值,您只需要将结果除以元素数。您可以使用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)
请注意,这使用整数进行计算 - 因此它也会进行整数除法。如果您正在使用浮点数,则可以将0
常量更改为0.0
,F#将推断该函数适用于浮点数。
如果您想要更高级的解决方案,那么您可以定义自己的类型来表示颜色。对于正确的类型定义,您只需使用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 }
该记录包含一个重载+
运算符,Zero
成员和DivideByInt
方法,可实现以下目标:
[ {R=255;G=0;B=0}; {R=0;G=128;B=255} ]
|> Seq.average
答案 1 :(得分:1)
让我们一步一步(来自F#Interactive的列表,以显示类型推断如何处理我们的代码)。
总结两个3元组:
> let sumRGB (r1,g1,b1) (r2,g2,b2) = (r1+r2, g1+g2, b1+b2);;
val sumRGB :
r1:int * g1:int * b1:int -> r2:int * g2:int * b2:int -> int * int * int
3元组的总和序列:
> let sumRGBSeq seq = seq |> Seq.fold sumRGB (0,0,0);;
val sumRGBSeq : seq:seq<int * int * int> -> int * int * int
测试解决方案:
> let source = [(123,143,136);(177,284,248);(143,182,252)];;
val source : (int * int * int) list =
[(123, 143, 136); (177, 284, 248); (143, 182, 252)]
> sumRGBSeq source;;
val it : int * int * int = (443, 609, 636)
<强>更新强>
当@TomasPetricek指针输出时,您当前的代码不计算平均值,它计算3元组序列的总和。
答案 2 :(得分:0)
这个版本不包括平均值(正如Tomas指出的那样,内置平均值不适用于int),使用List
代替Seq
,它可能效率不高,但它更简洁:
let (|||>) (a,b,c) fn = (fn a, fn b, fn c)
let sumRGB rgb = rgb |> List.unzip3 |||> List.sum