haskell 如何用fold分組

時間 2021-06-08 19:49:36

1樓:葉芝秋

我提供一種方法

groupBynxs

=snd

$foldr

group(-

1,)[(

i`quot`n

,x)|

(i,x

)<-(zip[0

..]xs)]

where

group(i

,x)(

j,yss)|i

==j=(

i,(x

:head

yss):(

tail

yss))

|otherwise=(

i,[x

]:yss)

演算法思想:首先從0開始列舉元素,並將索引和元素zip成乙個(index, element)元組的list。然後對每個元組,將index 整除以n從而將索引壓縮到[0, div (length xs) n] 這個範圍,這時候,處於相同組的元素將擁有相同的索引。

然後我們對zip過的資料使用group函式進行foldr摺疊。為了能夠識別新加入的元素是否與上次處理的元素處於同一組,我們還必須將上次處理的元素所在的組號作為輸入(該引數初始化為-1,因為元素的組號都是自然數)。最後,我們取摺疊所得元組的second作為groupBy函式的返回值。

groupBynxs

=snd

$foldr

group(-

1,)(

zipWith

((,).(`

quot`n

))[0..

]xs)where

group(i

,x)(

j,yss)|i

==j=(

i,(x

:head

yss):(

tail

yss))|1

==1=(

i,[x

]:yss)

測試groupByn=

snd.

foldr

group(-

1,).

index

where

index

=zipWith

((,).(`

quot`n

))[0..

]group(i

,x)(

j,yss)|i

==j=(

i,(x

:head

yss):(

tail

yss))|i

/=j=(

i,[x

]:yss)

2樓:

-- |

---- >>> chunksOf 3 [1..10]-- [[1,2,3],[4,5,6],[7,8,9],[10]]--chunksOf

::Int

->[a

]->[[a

]]chunksOfn=

gowherego

=goxs

=caseP.

splitAtnxs

of~(ys

,zs)->ys:

gozs

3樓:Ailrk

partitionInt

::Int

->[Int

]->[[Int

]]partitionIntn=

reverse

.foldl

part'[

]where

part'

xss@(as

:ass)x

|length

as==n=

[x]:

xss|

otherwise=(

as++[x

]):ass結果:

-> :

-> partition

-> partitionInt 3 [1..7]

[[1,2,3],[4,5,6],[7]]

-> partitionInt 3

[]看看part'的type

_ :: [[Int]] -> Int -> [[Int]]

再看看fold的type

foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

注意(b -> a -> b), 第乙個引數和base是乙個型別,第二個和Foldable 裡面的元素是乙個型別, 這兩個型別不一定要一樣的。其實像 `sum = fold (+) 0` 這種是特化成Int -> Int -> Int了, 但fold本身要更generic一點。

再舉乙個例子,不是haskell。這是我以前寫的乙個專案裡摘出來的, 目的是把乙個裝滿的array裡面名字相同的element分組,最後的返回值直接是乙個名字到object的map。 你看,fold的想法到處都可用到的。

/*** Partition elements with the same name into one list.

*/function

partitionUnique

>(list:T

),(()=>

);return

map;

})());

return

partitionedMap;}

// 這麼寫是有點怪啦

4樓:張砸鍋

ngroup

::Int

->[a

]->[[a

]]ngroupn=

rst.

foldlf(,0,

)wheref::

([[a

]],Int,[

a])->

a->([[a

]],Int,[

a])f(

r,i,

m)x=

ifi<

nthen(r

,i+1

,m++[

x])else(r

++[m],

1,[x

])rst

::([[

a]],

Int,[a

])->[[a

]]rst(r

,i,m

)=r++

[m]試一下效果:

λ stack ghci

Prelude> :

Prelude> ngroup 3 [1..9][[1,2,3],[4,5,6],[7,8,9]]Prelude> ngroup 3 [1..8][[1,2,3],[4,5,6],[7,8]]要是不用 fold 就簡單多了:

ngroup

::Int

->[a

]->[[a

]]ngroupn

=ngroup

nlist=[

take

nlist]++

ngroupn(

drop

nlist)

如何用Haskell實現物件導向程式設計?

圓角騎士魔理沙 剛剛讀完了Haskell s overlooked object system,給出了幾個proposal,最後深入研究用HList encode recursive record。很有意思,比如說,class,label是first class的,所以多重繼承玩得很溜,比如說可以自...

如何用 Final Cut Pro X 合成一人分飾兩角的鏡頭?

SiRius Geng 背景不變的話,用固定機位拍兩遍,然後用一下遮罩。如果背景有變化,兩人還會有交錯的話,一遍實拍,然後第二遍用綠幕,放到FCP裡扣像調整就好了 Amene Amakawa 嚴肅臉 盜圖者,所有關於下體不好的事情都會發生在你身上的!哼唧!益 FCPX 公升級了很多,但是我還是要強調...

Haskell 中如何描述 product 作為 的 category?

張智浩 首先這個問題表述確實不大清楚,至少不是嚴格的數學語言 或者說不大精確 我把問題重新表述如下 此處快速回憶範疇的定義,略 或可參見維基百科 性質 對任意三個物件 復合對映 是同構。不精確的問題 若乙個範疇滿足性質 我們能對它說些什麼嗎?從某些 可能沒用的 經驗來看,這種問題一般就取特殊值就完了...