F#递归创建一个int列表

时间:2014-10-17 20:00:50

标签: list recursion f# tail-recursion

所以我有一个位图,它是一个int列表,每个像素代表rgb 3个索引。 图像的一行是一个列表,我正在尝试递归编辑此int列表列表并吐出另一个int列表列表。问题是,当我到达行的末尾时,我希望它创建另一个列表。现在,代码每行创建一个像素,每个列表创建3个值,并使图像直线向下,因此每个递归调用创建一个新列表。我希望它在没有达到宽度结束时继续在同一个列表上。这里的代码更有意义,因为我很难解释它。

let rec GrayscaleImage(width:int, widthVar:int, image:int list list) =
    match image with
    |[] -> []
    |_ -> let r = image.Head.Head 
          let g = image.Head.Tail.Head
          let b = image.Head.Tail.Tail.Head
          let average = (int)((r+g+b)/3) 
          if widthVar > 3 then [average; average; average] :: GrayscaleImage(width, widthVar - 1, image.Tail.Tail.Tail)
          else ???

首先在if之后它将创建一个新的列表,我希望它继续平均列表。(它是灰度图像btw)然后在其他我知道它应该做的事情就像在if上做的那样但可能不完全一样。我对如何去做这件事感到非常困惑。任何帮助都将不胜感激。

编辑: 我在以下代码中取得了一些进展

let rec BuildRowGrayscale(cols:int, a:int) =
    match cols with
    |0 -> []
    |_ -> a :: a :: a :: BuildRowGrayscale (cols-1) a

let rec GrayscaleImage(width:int, height:int, depth:int, image:int list list) =
    match image with
    |[] -> []
    |_ -> 
          let r = image.Head.Head
          let g = image.Head.Tail.Head
          let b = image.Head.Tail.Tail.Head
          let avg = (int)((r+g+b)/3)
          (BuildRowGrayscale width avg) :: GrayscaleImage(width, height, depth, image.Tail)

但它拒绝在(BuildRowGrayscale width avg)BuildRowGrayscale (cols-1)处进行编译 “此值不是函数,无法应用”

2 个答案:

答案 0 :(得分:3)

发表评论后,我认为这就是你要做的事情:

let rec GrayscaleImage image =
    let rec BuildRowGrayscale = 
        function
        | [] -> []
        | r::g::b::rest -> 
            let avg = (r+g+b)/3
            (avg :: avg :: avg :: BuildRowGrayscale rest)
        | _ -> failwith "Invalid image"
    match image with
    | []        -> []
    | row::rest -> BuildRowGrayscale row :: GrayscaleImage rest

或使用List.replicateList.map

let GrayscaleImage =
    let rec BuildRowGrayscale = function
        | []            -> []
        | r::g::b::rest -> List.replicate 3 ((r+g+b)/3) @ BuildRowGrayscale rest
        | _             -> failwith "Invalid image"
    List.map BuildRowGrayscale

很抱歉,但是您指定宽度的事实让我觉得您也在改变原始结构,但如果结构没有改变,您不需要指定宽度,它就是&#39 ; s隐含在原始结构中。

答案 1 :(得分:1)

我假设image包含您图像的像素。由于您只进行按像素操作,因此您只需映射外部列表。

let GrayscaleImage =
    let avg = function
        | r::g::b::_ ->
            let average = (r+g+b)/3
            [average; average; average]
        | _ -> failwith "expected 3 colors"
    List.map avg