List 递归地创建一个int列表

List 递归地创建一个int列表,list,recursion,f#,tail-recursion,List,Recursion,F#,Tail Recursion,所以我有一个位图,它是一个整数列表,每像素3个索引代表rgb。 图像的一行是一个列表,我试图递归地编辑这个int列表,然后吐回另一个int列表。问题是,当我到达一行的末尾时,我希望它创建另一个列表。现在,代码每行创建一个像素,即每列表创建3个值,并使图像成为一条直线,因此每次递归调用都会创建一个新列表。我希望它继续在同一个列表上,而它还没有到达宽度的末尾。这里的代码更合理一些,因为我很难解释它 let rec GrayscaleImage(width:int, widthVar:int, ima

所以我有一个位图,它是一个整数列表,每像素3个索引代表rgb。 图像的一行是一个列表,我试图递归地编辑这个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之后,它将创建一个新的列表,我希望它继续这个平均值列表。顺便说一句,它对图像进行灰度缩放,然后在其他情况下,我知道它应该像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)
但它拒绝编译BuildRowGrayscaleWidthAvg和BuildRowGrayscaleCols-1 此值不是函数,无法应用

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

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

在你发表评论之后,我认为这就是你想要做的:

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.replicate和List.map:


很抱歉,您指定的宽度让我觉得您也在更改原始结构,但是如果结构没有更改,则不需要指定宽度,它隐含在原始结构中。

只是一个提示-避免使用.Head和.tail。我会将|->更改为| r::g::b::rest如果您想在到达行末尾时创建一个新列表,您的结果将是一个int列表,用于更新do BuildRowGrayscale width、avg和BuildRowGrayscale cols-1,a您在定义中使用了元组形式。BuildRowGrayscale在传递元组int和int时接受元组,就像它的类型签名是int->int->int list一样。这将无法正常工作,因为上一次迭代中的g在下一次迭代中将变为r,我不认为这是他想要的。它不会编译,因为它返回一个列表的列表。。等等,不确定有多少错误是相当长的,但我可以看到这种方法将如何工作我只是有一个艰难的时间使其编译,因为函数必须返回一个int列表list@Man它为我编译:val GrayscaleImage:int list->int listlist@John什么迭代?不涉及递归。使用List.Map进行迭代非常感谢所有这些代码帮助我非常了解如何进行此操作唯一的误解是您这样做时认为结构是[1,1,1],[2,2,2],[5,10255]等,而它类似于[1,1,1,2,2,2,2,2,5,10255]下一个列表表示下一行,因此每个列表都是图像的一个水平像素行。目前的代码不工作,因为这一点,我认为我可以让它工作,虽然我真的很难与F。我肯定是一个面向对象的程序员,我甚至更愿意做C而不是F个人哈哈。哦,如果结构没有改变,那么你不需要指定宽度。你只需要调整灰度。请参阅更新。不客气。作为交换,你教我如何使用灰度,我不知道这只是一个r g b平均值;
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