2011-03-06 84 views
5

在Haskell中,有兩個函數允許對項目列表執行操作,以便將其減少爲單個值。 (當然有兩個以上,但這些是我感興趣的兩個。)他們是foldl1foldr1。如果要執行的操作是commutative(如添加),則使用這些操作並不重要。結果將是相同的。但是,如果操作是而不是可交換(例如,減法),則這兩者產生非常不同的結果。例如:在J中實現Haskell foldl1的最有效方法是什麼?

foldr1 (-) [1..9] 
foldl1 (-) [1..9] 

答案是第一個是5,第二個是-43。殲等效的foldr1是插入副詞,/,例如

-/ 1+i.9 

其爲foldr1 (-) [1..9]等效。我想在J中創建一個類似於插入副詞的副詞,但向左摺疊而不是向右摺疊。我能想出的最好的是以下幾點:

foldl =: 1 : 'u~/@|.' 

因此,我們可以說:

- foldl 1+i.9 

,並得到-43的答案,這是從左側倍的預期。

在J中有更好的方法嗎?出於某種原因,顛倒y的論點對我來說似乎並不高效。也許有一種方法可以做到這一點,而不必訴諸於此。

+1

我不知道是否有除了翻轉數組之外的東西,不管它看起來多麼實用。人們會認爲(或者希望)Haskell不會那麼做,只是從最後起作用... – MPelletier 2011-03-07 16:04:09

+0

我的意思是「不管多麼實際。」 – MPelletier 2011-03-07 16:16:08

回答

2

我不認爲這是一個更好的方式來倍左比你描述:

(v~)/(|. list) 

這是一個非常自然的方式,是一個幾乎「文本」執行的定義。反轉列表的成本非常小(imo)。

執行左摺疊的其他顯而易見的方法是設置

new_list = (first v second) v rest 

如:

foldl_once =: 1 :'(u/0 1 { y), (2}. y)' 
foldl =: 1 :'(u foldl_once)^:(<:#y) y' 

這樣:

- foldl >:i.9 
_43 

而是用自己的方式進行優於這在空間和時間。

+0

我給你獎,雖然ephemient的回答很有趣,因爲我認爲很明顯,我的解決方案可能是最好的,但我無法證明它。 – 2011-03-12 22:33:32

1
($:@}:-{:)^:(1<#) 1+i.9 
_43 

不知道它是否有更多(或更少)的效率。

+0

很難說。在4500以下的數字,您的解決方案和我的即時。之後,你的導致堆棧錯誤,我的工作很好。所以從這個意義上說,我的效率更高,但除了資源之外很難說哪個更快。 – 2011-03-08 05:27:02

+0

哦,我想我會補充說你的聰明和教育。 – 2011-03-08 05:27:26

相關問題