我刚刚发现this post并想知道如何在Haskell中做类似的事情。在下面,我只是简化了我有困难的部分:高效地访问像素
我有一个包含大量2D坐标的列表。对于simplicitys的缘故,让我们假设该列表包含Int
坐标是所有范围内的0 - 1023
points :: [(Int,Int)] -- long list of points
的目标现在具有图像(让我们说img :: [[Int]]
其中img
和每个条目其长度为1024
),其中(img!!i)!!j
是(i,j)
在points
(它将被映射到一些灰度值)的出现次数。
我试了一下,到目前为止:
- 如果我只是用遍历
points
并试图incerment一些二维数组的进入i,j
,约捡一些入门i,j
,并增加了部分的必要途径这一方面非常麻烦,可能效率不高,另一方面使用!!
容易出现index too large
错误。 - 效率稍高一点的方法:对于坐标
(i,j)
的每个对,使用partition
来筛选出(i,j)
条目并对它们进行计数,并将其余列表传递给下一对坐标。这样我们得到一个(i,j, count)
的列表,我们只需要将count
插入每个像素i,j
一次,但在我看来,这仍然不是很优雅。
所以,你可以建议如何做到这一点的更高效,更优雅功能任何方式解决?
这只是一个示例性问题,因为我经常遇到类似的问题,只发现不满意的解决方案。
编辑:由于这里要求是这种代码的一个例子:
main = putStrLn "before:" >> print myImg >> putStrLn "after:" >> print myImg2
>> putStrLn "output of our \"image\":" >> print outImg
n :: Int
n = 4
-- example for "increment"
myImg = [[n..n+3]|n<-[1,5..16]] :: [[Int]]
myImg2 = increment myImg 2 3 10000
-- example for our application
zeroImg = [[0,0,0,0]|_<-[0,0,0,0]]
outImg = foldl (\img (i,j) -> increment img i j 1) zeroImg points
-- our "data" (here im just filling this with arbitrary numbers)
points = [(i `mod` n,j `mod` n)|i <-[1..14],j<-[i..77+i]]
-- not very elegant code
increment :: [[Int]] -> Int -> Int -> Int -> [[Int]]
increment img i j v = a ++ [x ++ [y + v] ++ z] ++ c -- increments the "pixel" (i,j) by v
where
a = take i img
b = img !! i
c = drop (i+1) img
x = take j b
y = b !! j
z = drop (j+1) b
有些语言可以互换使用这些术语,这取决于您所说的语言,但这不是重点。我认为我们是否使用列表并不重要,难点在于访问和使用索引更改某些内容。如果你坚持你可以用例如来自'Codec.Picture'的'Image',但我的问题基本保持不变。 – flawr
您有关*更有效和优雅的功能方式*的问题。所以,我写了什么使用列表这不是有效的方式。关于*优雅的功能方式*,也许如果你添加你的解决方案,它可以帮助我们在这里了解你的问题? – freestyle
通常,解决Haskell上的这些问题并不意味着什么,因为您是从对命令式代码很方便的数据开始的。但是你应该从那些方便功能方式的数据开始。例如,您可以通过添加两个图像来更改此问题。其中一个将是你的原始图像,第二个将是一个“从你的观点创建”的图像。 – freestyle