当前位置:  开发笔记 > 编程语言 > 正文

如何使这段代码更紧凑和惯用?

如何解决《如何使这段代码更紧凑和惯用?》经验,为你挑选了1个好方法。

Hullo all.

我是一名C#程序员,在我的空闲时间探索F#.我在2D中编写了以下用于图像卷积的小程序.

open System

let convolve y x = 
  y |> List.map (fun ye -> x |> List.map ((*) ye))
    |> List.mapi (fun i l -> [for q in 1..i -> 0] @ l @ [for q in 1..(l.Length - i - 1) -> 0])
    |> List.reduce (fun r c -> List.zip r c |> List.map (fun (a, b) -> a + b))   

let y = [2; 3; 1; 4]
let x = [4; 1; 2; 3]
printfn "%A" (convolve y x)

我的问题是:上面的代码是一个惯用的F#?可以更简洁吗?(例如,是否有一些更短的方法来生成0的填充列表(为此我在代码中使用了列表理解)).任何可以改善其性能的变化?

任何帮助将不胜感激.谢谢.

编辑:

谢谢Brian.我没有得到你的第一个建议.以下是我的代码在应用您的第二个建议后的样子.(我还抽象出了list-fill操作.)

open System

let listFill howMany withWhat = [for i in 1..howMany -> withWhat]

let convolve y x = 
  y |> List.map (fun ye -> x |> List.map ((*) ye))
    |> List.mapi (fun i l -> (listFill i 0) @ l @ (listFill (l.Length - i - 1) 0))
    |> List.reduce (List.map2 (+))

let y = [2; 3; 1; 4]
let x = [4; 1; 2; 3]
printfn "%A" (convolve y x)

还有什么可以改进吗?等待更多建议......



1> Tomas Petric..:

正如Brian所提到的,使用@通常是有问题的,因为操作员无法有效地实现(简单)功能列表 - 它需要复制整个第一个列表.

我认为Brians的建议是编写一个可以立即生成列表的序列生成器,但这有点复杂.您必须将列表转换为数组,然后编写如下内容:

let convolve y x =  
  y |> List.map (fun ye -> x |> List.map ((*) ye) |> Array.ofList) 
    |> List.mapi (fun i l -> Array.init (2 * l.Length - 1) (fun n -> 
        if n < i || n - i >= l.Length then 0 else l.[n - i]))
    |> List.reduce (Array.map2 (+))

一般来说,如果性能是一个重要的问题,那么你可能还需要使用数组(因为通过索引访问元素可以最好地解决这种问题).使用数组有点困难(你需要正确的索引),但F#中的完美方法.

无论如何,如果你想用列表写这个,那么这里有一些选项.您可以在任何地方使用序列表达式,如下所示:

let convolve y (x:_ list) =  
  [ for i, v1 in x |> List.zip [ 0 .. x.Length - 1] ->
      [ yield! listFill i 0
        for v2 in y do yield v1 * v2
        yield! listFill (x.Length - i - 1) 0 ] ]
  |> List.reduce (List.map2 (+))

...或者您也可以组合这两个选项,yield!并在您传递给的lambda函数中使用嵌套序列表达式(用于生成零和列表)List.mapi:

let convolve y x =  
  y |> List.map (fun ye -> x |> List.map ((*) ye)) 
    |> List.mapi (fun i l -> 
         [ for _ in 1 .. i do yield 0
           yield! l 
           for _ in 1 .. (l.Length - i - 1) do yield 0 ])
    |> List.reduce (List.map2 (+))    

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有