我剛剛發現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